在 CakePHP 3 中使用动态 AJAX 加载分页和搜索关联查询
Paginate and search associated query with dynamic AJAX loading in CakePHP 3
我正在使用 CakePHP 3.7 开发应用程序。
我们有 3 个数据库 table,具有以下层次结构。这些 table 根据 Table 类:
正确关联
regulations
groups
filters
(关联在上一个问题中显示:CakePHP 3 - association is not defined - even though it appears to be)
我可以从所有三个 table 中获取所有数据,如下所示:
$regulations = TableRegistry::getTableLocator()->get('Regulations');
$data = $regulations->find('all', ['contain' => ['Groups' => ['Filters']]]);
$data = $data->toArray();
filters
table 包含 >1300 条记录。因此,我正在尝试构建一个功能,当用户向下滚动页面时,通过 AJAX 调用逐步加载数据,类似于此处描述的内容:https://makitweb.com/load-content-on-page-scroll-with-jquery-and-ajax/
问题是我需要能够计算返回的总行数。但是,此数据存在于 3 table 秒内。
如果我执行 debug($data->count());
,它将输出 8,因为 regulations
table 中有 8 行。理想情况下,我需要计算它在 filters
table(~1300 行)中返回的行数,就初始负载而言,这是大多数数据存在的地方。
问题更加复杂,因为此功能允许用户执行搜索。给定的搜索词可能存在于所有 3 个 table 中,table 中的 1 - 2 个中,或者根本不存在。我不知道这样做的正确方法是尝试计算每个 table 中返回的行数还是总体行数?
我已阅读 Cake 文档中的 and Filtering By Associated Data。
附加信息
问题似乎归结为如何使用 Cake 提供的 ORM 语法编写查询。以下(纯 MySQL)查询实际上会执行我想要的操作。假设用户搜索了 "Asbestos":
SELECT
regulations.label AS regulations_label,
groups.label AS groups_label,
filters.label AS filters_label
FROM
groups
JOIN regulations
ON groups.regulation_id = regulations.id
JOIN filters
ON filters.group_id = groups.id
WHERE regulations.label LIKE '%Asbestos%'
OR groups.label LIKE '%Asbestos%'
OR filters.label LIKE '%Asbestos%'
ORDER BY
regulations.id ASC,
groups_label ASC,
filters_label ASC
LIMIT 0,50
假设返回了 203 行。 LIMIT
条件意味着我得到前 50 个。前端的一些 js(就其工作方式而言并不真正相关)将在用户滚动到底部时进行 ajax 调用重新 运行 具有不同限制的此查询(例如 LIMIT 51, 100
用于下一组结果)。
问题似乎有两个方面:
如果我使用 Cake 的 ORM 语法编写查询,则输出是一个嵌套数组。相反,如果我用普通的 SQL 编写它,它会返回一个 table,它只有 3 列,其中包含我需要显示的标签。就在页面上输出所需数据而言,这种结构更容易使用。
第二个 - 也许 更重要的问题 - 是我看不出你如何在 ORM 中编写 LIMIT
条件由于 1 中描述的嵌套结构,语法使这项工作有效。例如,如果我添加 $data->limit(50)
,它只会对 regulations
table 施加此限制。因此,本质上搜索适用于 regulations
中前 50 行的任何关联数据。与我在 MySQL 中编写的 LIMIT
条件相反,它会考虑整个结果集,其中包括来自所有 3 个 table 的列。
为了进一步阐述第 2 点,假设 table 包含以下行数:
regulations
: 150
groups
: 1000
filters
: 5000
如果我使用 $data->limit(50)
,它将仅适用于 regulations
table 中的 50 行。我需要在所有 3 table 中搜索给定术语的所有行后应用 LIMIT
结果集。
使用查询生成器创建该查询非常简单,如果您想要连接非 1:1 关联,则使用 *JoinWith()
方法而不是 contain()
,在本例中为 innerJoinWith()
,类似于:
$query = $GroupsTable
->find()
->select([
'regulations_label' => 'Regulations.label',
'groups_label' => 'Groups.label',
'filters_label' => 'Filters.label',
])
->innerJoinWith('Regulations')
->innerJoinWith('Filters')
->where([
'OR' => [
'Regulations.label LIKE' => '%Asbestos%',
'Groups.label LIKE' => '%Asbestos%',
'Filters.label LIKE' => '%Asbestos%',
],
])
->order([
'Regulations.id' => 'ASC',
'Groups.label' => 'ASC',
'Filters.label' => 'ASC',
]);
另见
我正在使用 CakePHP 3.7 开发应用程序。
我们有 3 个数据库 table,具有以下层次结构。这些 table 根据 Table 类:
正确关联regulations
groups
filters
(关联在上一个问题中显示:CakePHP 3 - association is not defined - even though it appears to be)
我可以从所有三个 table 中获取所有数据,如下所示:
$regulations = TableRegistry::getTableLocator()->get('Regulations');
$data = $regulations->find('all', ['contain' => ['Groups' => ['Filters']]]);
$data = $data->toArray();
filters
table 包含 >1300 条记录。因此,我正在尝试构建一个功能,当用户向下滚动页面时,通过 AJAX 调用逐步加载数据,类似于此处描述的内容:https://makitweb.com/load-content-on-page-scroll-with-jquery-and-ajax/
问题是我需要能够计算返回的总行数。但是,此数据存在于 3 table 秒内。
如果我执行 debug($data->count());
,它将输出 8,因为 regulations
table 中有 8 行。理想情况下,我需要计算它在 filters
table(~1300 行)中返回的行数,就初始负载而言,这是大多数数据存在的地方。
问题更加复杂,因为此功能允许用户执行搜索。给定的搜索词可能存在于所有 3 个 table 中,table 中的 1 - 2 个中,或者根本不存在。我不知道这样做的正确方法是尝试计算每个 table 中返回的行数还是总体行数?
我已阅读 Cake 文档中的
附加信息
问题似乎归结为如何使用 Cake 提供的 ORM 语法编写查询。以下(纯 MySQL)查询实际上会执行我想要的操作。假设用户搜索了 "Asbestos":
SELECT
regulations.label AS regulations_label,
groups.label AS groups_label,
filters.label AS filters_label
FROM
groups
JOIN regulations
ON groups.regulation_id = regulations.id
JOIN filters
ON filters.group_id = groups.id
WHERE regulations.label LIKE '%Asbestos%'
OR groups.label LIKE '%Asbestos%'
OR filters.label LIKE '%Asbestos%'
ORDER BY
regulations.id ASC,
groups_label ASC,
filters_label ASC
LIMIT 0,50
假设返回了 203 行。 LIMIT
条件意味着我得到前 50 个。前端的一些 js(就其工作方式而言并不真正相关)将在用户滚动到底部时进行 ajax 调用重新 运行 具有不同限制的此查询(例如 LIMIT 51, 100
用于下一组结果)。
问题似乎有两个方面:
如果我使用 Cake 的 ORM 语法编写查询,则输出是一个嵌套数组。相反,如果我用普通的 SQL 编写它,它会返回一个 table,它只有 3 列,其中包含我需要显示的标签。就在页面上输出所需数据而言,这种结构更容易使用。
第二个 - 也许 更重要的问题 - 是我看不出你如何在 ORM 中编写
LIMIT
条件由于 1 中描述的嵌套结构,语法使这项工作有效。例如,如果我添加$data->limit(50)
,它只会对regulations
table 施加此限制。因此,本质上搜索适用于regulations
中前 50 行的任何关联数据。与我在 MySQL 中编写的LIMIT
条件相反,它会考虑整个结果集,其中包括来自所有 3 个 table 的列。
为了进一步阐述第 2 点,假设 table 包含以下行数:
regulations
: 150groups
: 1000filters
: 5000
如果我使用 $data->limit(50)
,它将仅适用于 regulations
table 中的 50 行。我需要在所有 3 table 中搜索给定术语的所有行后应用 LIMIT
结果集。
使用查询生成器创建该查询非常简单,如果您想要连接非 1:1 关联,则使用 *JoinWith()
方法而不是 contain()
,在本例中为 innerJoinWith()
,类似于:
$query = $GroupsTable
->find()
->select([
'regulations_label' => 'Regulations.label',
'groups_label' => 'Groups.label',
'filters_label' => 'Filters.label',
])
->innerJoinWith('Regulations')
->innerJoinWith('Filters')
->where([
'OR' => [
'Regulations.label LIKE' => '%Asbestos%',
'Groups.label LIKE' => '%Asbestos%',
'Filters.label LIKE' => '%Asbestos%',
],
])
->order([
'Regulations.id' => 'ASC',
'Groups.label' => 'ASC',
'Filters.label' => 'ASC',
]);
另见