CakePHP 4 -从另一个表中查询最新状态

mi7gmzs6  于 2022-11-11  发布在  PHP
关注(0)|答案(2)|浏览(138)

我正在使用CakePHP 4构建一个应用程序,该应用程序显示文档清单和每个文档的最新状态。
这些表相当简单:

  • documents:它包含一个文档列表,每个文档都有一个唯一的id、一个友好的名称、一个文件名等。
  • statuses:这包括文档在应用程序中可以经历的大约10种不同状态的列表(例如“已上传”、“已请求审阅”、“已审阅”、“已拒绝”等)。每种状态都有唯一的idname(名称是状态的文本,例如“已上传”、“已请求审阅”等)。
  • 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表中的相应列。
我知道在这个查询中需要一些额外的逻辑,将JOINMap到documents_statuses表,然后以LIMIT为1的降序对记录进行排序,以获得每个文档的最新状态。我还需要执行进一步的JOIN,以便documents_statuses.status_id返回相应的statuses.name
我知道我可以修改查询以包含documents_statusesstatuses

$documents = $this->Documents->contain(['DocumentsStatuses', 'Statuses'])->find();

但是我不知道如何在这个查询中循环documents_statuses中的记录,并执行->orderDesc->limit(1)以获得最新的记录。此外,我还知道要获得statuses.name,我需要让这个查询连接documents_statuses.status_idstatuses.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
4jb9z9bj

4jb9z9bj1#

它可以用一个稍微复杂的JOIN来完成;请参阅[groupwise-max]标签或我的Groupwise-Max
或者,您可以使用不同的模式模式:

  • Current--它总是有最新的“状态”(加上其他信息)。每个文档将有一行。
  • History--基本上就像你现在拥有的一样。但是这并不是为了找到“当前状态”而查看的。这个表每个文档有很多行。

您的代码将需要INSERT INTO HistoryUPDATE Current来更新status。(实际上,如果您需要在该行还不存在时执行Insert,则Update可以是一个IODKU。)
所讨论的查询将只是SELECT ... FROM Current ...--不需要连接。

ax6ht2ek

ax6ht2ek2#

$documents = $this->Documents->contain(['DocumentsStatuses'=>function(Query $q){ return $q->contain(['Statuses'])->orderDesc->limit(1);}])->find();

book.cakephp.org

相关问题