我正在使用CakePHP 4构建一个应用程序,该应用程序显示文档清单和每个文档的最新状态。
这些表相当简单:
documents
:它包含一个文档列表,每个文档都有一个唯一的id
、一个友好的名称、一个文件名等。statuses
:这包括文档在应用程序中可以经历的大约10种不同状态的列表(例如“已上传”、“已请求审阅”、“已审阅”、“已拒绝”等)。每种状态都有唯一的id
和name
(名称是状态的文本,例如“已上传”、“已请求审阅”等)。documents_statuses
:这是一个历史记录表,其中包含文档所经历的所有状态。任何给定的文档(documents.id
)可以在此表中多次出现(使用外键documents_statuses.document_id
引用相关的documents.id
)。它也有一个documents_statuses.status_id
对应于上面提到的状态表中的statuses.id
。这里的每一行都有CakePHP'的常规created
时间戳,这样我们就知道行是何时插入的。这足以告诉我们文档何时进入特定状态的日期/时间。
我尝试做的是输出一个documents
的列表,并在我的表中显示来自documents_statuses
的最新状态。表的HTML结构很简单,包含3个标题:
- 文件名称
- 文件名称
- 上次状态
编写一个查询来获取前2列的数据很容易,因为的数据属于documents
表:
// src/Controller/DocumentsController.php
public function index()
{
$documents = $this->Documents->find();
$documents = $documents->paginate($document);
$this->set('documents', $documents);
}
然后,在我的模板中,我可以引用$documents->name
和$documents->filename
,以输出documents
表中的相应列。
我知道在这个查询中需要一些额外的逻辑,将JOIN
Map到documents_statuses
表,然后以LIMIT
为1的降序对记录进行排序,以获得每个文档的最新状态。我还需要执行进一步的JOIN
,以便documents_statuses.status_id
返回相应的statuses.name
。
我知道我可以修改查询以包含documents_statuses
和statuses
:
$documents = $this->Documents->contain(['DocumentsStatuses', 'Statuses'])->find();
但是我不知道如何在这个查询中循环documents_statuses
中的记录,并执行->orderDesc->limit(1)
以获得最新的记录。此外,我还知道要获得statuses.name
,我需要让这个查询连接documents_statuses.status_id
和statuses.id
以返回statuses.name
(例如“uploaded”,“review requested”等)。
应用程序已bake
'd,模型关联已正确定义。
在CakePHP文档中是否可以描述一些等效的东西?
编辑-原始SQL
下面的SQL语句和我用ORM编写的语句是一样的。问题不在于对SQL语句的理解,而在于用CakePHP的ORM语法来编写。同样,如果有一个“更好”的方法来编写这个查询语句,我很感兴趣,但是这个问题的目的是如何用CakePHP的ORM来实现这个功能。
SELECT
documents.name,
documents_statuses.created,
statuses.name
FROM documents
LEFT JOIN
(SELECT documents_id, MAX(created) AS created
FROM documents_statuses
GROUP BY documents_id
) recent_statuses
ON documents.id = recent_statuses.documents_id
LEFT JOIN documents_statuses
ON documents.id = documents_statuses.documents_id AND recent_statuses.created = documents_statuses.created
LEFT JOIN statuses
ON documents_statuses.status_id = statuses.id
2条答案
按热度按时间4jb9z9bj1#
它可以用一个稍微复杂的
JOIN
来完成;请参阅[groupwise-max]
标签或我的Groupwise-Max或者,您可以使用不同的模式模式:
Current
--它总是有最新的“状态”(加上其他信息)。每个文档将有一行。History
--基本上就像你现在拥有的一样。但是这并不是为了找到“当前状态”而查看的。这个表每个文档有很多行。您的代码将需要
INSERT INTO History
和UPDATE Current
来更新status
。(实际上,如果您需要在该行还不存在时执行Insert,则Update可以是一个IODKU。)所讨论的查询将只是
SELECT ... FROM Current ...
--不需要连接。ax6ht2ek2#
book.cakephp.org