简体   繁体   English

在CakePHP 3中分页和搜索与动态AJAX加载相关的查询

[英]Paginate and search associated query with dynamic AJAX loading in CakePHP 3

I am working on an application in CakePHP 3.7. 我正在使用CakePHP 3.7中的应用程序。

We have 3 database tables with the following hierarchy. 我们有3个具有以下层次结构的数据库表。 These tables are associated correctly according to the Table classes: 这些表根据Table类正确关联:

  • regulations
    • groups
      • filters

(The associations are shown in a previous question: CakePHP 3 - association is not defined - even though it appears to be ) (该关联已在上一个问题中显示: CakePHP 3-未定义关联-即使它看起来像是

I can get all of the data from all three tables as follows: 我可以从所有三个表中获取所有数据,如下所示:

$regulations = TableRegistry::getTableLocator()->get('Regulations');
$data = $regulations->find('all', ['contain' => ['Groups' => ['Filters']]]);
$data = $data->toArray();

The filters table contains >1300 records. filters表包含> 1300条记录。 I'm therefore trying to build a feature which loads the data progressively via AJAX calls as the user scrolls down the page similar to what's described here: https://makitweb.com/load-content-on-page-scroll-with-jquery-and-ajax/ 因此,我正在尝试构建一个功能,该功能可以在用户向下滚动页面时通过AJAX调用逐步加载数据,类似于此处所述: https : //makitweb.com/load-content-on-page-scroll-with- jquery的和- AJAX /

The problem is that I need to be able to count the total number of rows returned. 问题是我需要能够计算返回的总行数。 However, the data for this exists in 3 tables. 但是,此数据存在于3个表中。

If I do debug($data->count()); 如果我debug($data->count()); it will output 8 because there are 8 rows in the regulations table. 由于regulations表中有8行,因此它将输出8。 Ideally I need a count of the rows it's returning in the filters table (~1300 rows) which is where most of the data exists in terms of the initial load. 理想情况下,我需要对它在filters表(〜1300行)中返回的行进行计数,这是大多数数据在初始加载方面存在的地方。

The problem is further complicated because this feature allows a user to perform a search. 由于该功能允许用户执行搜索,因此问题变得更加复杂。 It might be the case that a given search term exists in all 3 tables, 1 - 2 of the tables, or not at all. 给定的搜索词可能存在于所有3个表(表的1-2)中,或者根本不存在。 I don't know whether the correct way to do this is to try and count the rows returned in each table, or the rows overall? 我不知道执行此操作的正确方法是尝试计算每个表中返回的行还是计算总行数?

I've read How to paginate associated records? 我已经阅读了如何对相关记录进行分页? and Filtering By Associated Data in the Cake docs. 和在Cake文档中按关联数据进行过滤

Additional information 附加信息

The issue seems to come down to how to write a query using the ORM syntax Cake provides. 问题似乎归结于如何使用Cake提供的ORM语法编写查询。 The following (plain MySQL) query will actually do what I want. 以下(普通MySQL)查询实际上将执行我想要的操作。 Assuming the user has searched for "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

Let's say there are 203 rows returned. 假设返回了203行。 The LIMIT condition means I am getting the first 50. Some js on the frontend (which isn't really relevant in terms of how it works) will make an ajax call as the user scrolls to the bottom of the page to re-run this query with a different limit (eg LIMIT 51, 100 for the next set of results). LIMIT条件意味着我将获得前50个。前端中的一些js(就其工作方式而言并没有真正的关系)将在用户滚动到页面底部以重新运行此代码时进行ajax调用查询具有不同的限制(例如LIMIT 51, 100下一组结果为LIMIT 51, 100 )。

The problem seems to be two fold: 问题似乎有两个方面:

  1. If I write the query using Cake's ORM syntax the output is a nested array. 如果我使用Cake的ORM语法编写查询,则输出为嵌套数组。 Conversely if I write it in plain SQL it's returning a table which has just 3 columns with the labels that I need to display. 相反,如果我用普通SQL编写它,它将返回一个表,该表只有3列带有需要显示的标签。 This structure is much easier to work with in terms of outputting the required data on the page. 就在页面上输出所需数据而言,此结构更容易使用。

  2. The second - and perhaps more important issue - is that I can't see how you could write the LIMIT condition in the ORM syntax to make this work due to the nested structure described in 1. If I added $data->limit(50) for example, it only imposes this limit on the regulations table. 第二个问题 ,也许是更重要的问题是,由于1中描述的嵌套结构,我看不到如何用ORM语法编写LIMIT条件来使之工作。如果我添加了$data->limit(50) ,例如,它仅将此限制强加在regulations表上。 So essentially the search works for any associated data on the first 50 rows in regulations . 因此,本质上,搜索可搜索regulations前50行中的任何关联数据。 As opposed to the LIMIT condition I've written in MySQL which would take into consideration the entire result set which includes the columns from all 3 tables. 与我在MySQL中编写的LIMIT条件相反,该条件将考虑整个结果集,其中包括来自所有3个表的列。

To further elaborate point 2, assume the tables contain the following numbers of rows: 为了进一步阐述第二点,假设表包含以下行数:

  • regulations : 150 regulations :150
  • groups : 1000 groups :1000
  • filters : 5000 filters :5000

If I use $data->limit(50) it would only apply to 50 rows in the regulations table. 如果我使用$data->limit(50) ,它将仅适用于regulations表中的50行。 I need to apply the LIMIT the result set after searching all rows in all 3 tables for a given term. 在搜索所有3个表中的所有行以获得给定术语后,我需要应用LIMIT结果集。

Creating that query using the query builder is pretty simple, if you want joins for non-1:1 associations, then use the *JoinWith() methods instead of contain() , in this case innerJoinWith() , something like: 使用查询生成器创建该查询非常简单,如果您想加入非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',
    ]);

See also 也可以看看

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM