【问题标题】:cakephp 3 order by query generates 14 queries with associate tables instead of 1cakephp 3 order by query 生成 14 个带有关联表的查询,而不是 1 个
【发布时间】:2016-07-12 21:53:59
【问题描述】:

我的 cakephp3 应用运行良好,现在我希望通过关联的表字段对一些查询进行排序。

当按当前模型中的字段排序时,查询工作正常。但是,如果我选择按关联表中的字段Models.field 进行排序,我现在会得到 14 个 sql 查询,而不是一个。但真正的问题是ORDER BY 没有包含在查询中。

我在具有 employee_id 和 course_id 字段的 CoursesEmployees 模型中。

CoursesEmployeesController.php

public function certificate() {
    $this->paginate = [
        'sortWhitelist' => [
            'Employees.surname', 'Courses.name', 'date_completed'
        ],
        'conditions' => ['CoursesEmployees.completed' => true, 'Employees.user_id' => $this->Auth->user('id')],
        'contain' => ['Employees', 'Courses'],
        'order' => ['Employees.name'=>'asc']
    ];
    $this->set('coursesEmployees', $this->paginate($this->CoursesEmployees));
}

如果我通过'order' => ['date_created'=>'asc'] 订购,我会收到一个查询,一切正常。

SELECT
    CoursesEmployees.id AS `CoursesEmployees__id`,
    CoursesEmployees.employee_id AS `CoursesEmployees__employee_id`,
    CoursesEmployees.course_id AS `CoursesEmployees__course_id`,
    CoursesEmployees.course_module_id AS `CoursesEmployees__course_module_id`,
    CoursesEmployees.cid AS `CoursesEmployees__cid`,
    CoursesEmployees.progress AS `CoursesEmployees__progress`,
    CoursesEmployees.modified AS `CoursesEmployees__modified`,
    CoursesEmployees.created AS `CoursesEmployees__created`,
    CoursesEmployees.completed AS `CoursesEmployees__completed`,
    CoursesEmployees.date_completed AS `CoursesEmployees__date_completed`,
    Employees.id AS `Employees__id`,
    Employees.user_id AS `Employees__user_id`,
    Employees.hotel_id AS `Employees__hotel_id`,
    Employees.name AS `Employees__name`,
    Employees.email AS `Employees__email`,
    Employees.surname AS `Employees__surname`,
    Employees.employee_num AS `Employees__employee_num`,
    Employees.modified AS `Employees__modified`,
    Employees.created AS `Employees__created`,
    Courses.id AS `Courses__id`,
    Courses.name AS `Courses__name`,
    Courses.course_lenght AS `Courses__course_lenght` 
FROM
    courses_employees CoursesEmployees 
INNER JOIN
    employees Employees 
        ON Employees.id = (
            CoursesEmployees.employee_id
        ) 
INNER JOIN
    courses Courses 
        ON Courses.id = (
            CoursesEmployees.course_id
        ) 
WHERE
    (
        CoursesEmployees.completed = 1 
        AND Employees.user_id = '1'
    ) 
ORDER BY
    CoursesEmployees.date_completed asc LIMIT 20 OFFSET 0

如果我'order' => ['Employees.name'=>'asc'](或字段名称的任何随机文本)我会得到 14 个 sql 查询,而主查询最后没有应有的顺序。

SHOW FULL COLUMNS FROM `courses_employees`  10  1

SHOW INDEXES FROM `courses_employees`   1   0

SELECT * FROM information_schema.key_column_usage AS kcu INNER JOIN information_schema.referential_constraints AS rc ON (kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME) WHERE kcu.TABLE_SCHEMA = 'deep_mind' AND kcu.TABLE_NAME = 'courses_employees' and rc.TABLE_NAME = 'courses_employees'    0   0

SHOW TABLE STATUS WHERE Name = 'courses_employees'  1   0

SHOW FULL COLUMNS FROM `employees`  9   1

SHOW INDEXES FROM `employees`   1   0

SELECT * FROM information_schema.key_column_usage AS kcu INNER JOIN information_schema.referential_constraints AS rc ON (kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME) WHERE kcu.TABLE_SCHEMA = 'deep_mind' AND kcu.TABLE_NAME = 'employees' and rc.TABLE_NAME = 'employees'    0   0

SHOW TABLE STATUS WHERE Name = 'employees'  1   0

SHOW FULL COLUMNS FROM `courses`    3   1

SHOW INDEXES FROM `courses` 1   0

SELECT * FROM information_schema.key_column_usage AS kcu INNER JOIN information_schema.referential_constraints AS rc ON (kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME) WHERE kcu.TABLE_SCHEMA = 'deep_mind' AND kcu.TABLE_NAME = 'courses' and rc.TABLE_NAME = 'courses'    0   0

SHOW TABLE STATUS WHERE Name = 'courses'    1   0

SELECT
    CoursesEmployees.id AS `CoursesEmployees__id`,
    CoursesEmployees.employee_id AS `CoursesEmployees__employee_id`,
    CoursesEmployees.course_id AS `CoursesEmployees__course_id`,
    CoursesEmployees.course_module_id AS `CoursesEmployees__course_module_id`,
    CoursesEmployees.cid AS `CoursesEmployees__cid`,
    CoursesEmployees.progress AS `CoursesEmployees__progress`,
    CoursesEmployees.modified AS `CoursesEmployees__modified`,
    CoursesEmployees.created AS `CoursesEmployees__created`,
    CoursesEmployees.completed AS `CoursesEmployees__completed`,
    CoursesEmployees.date_completed AS `CoursesEmployees__date_completed`,
    Employees.id AS `Employees__id`,
    Employees.user_id AS `Employees__user_id`,
    Employees.hotel_id AS `Employees__hotel_id`,
    Employees.name AS `Employees__name`,
    Employees.email AS `Employees__email`,
    Employees.surname AS `Employees__surname`,
    Employees.employee_num AS `Employees__employee_num`,
    Employees.modified AS `Employees__modified`,
    Employees.created AS `Employees__created`,
    Courses.id AS `Courses__id`,
    Courses.name AS `Courses__name`,
    Courses.course_lenght AS `Courses__course_lenght` 
FROM
    courses_employees CoursesEmployees 
INNER JOIN
    employees Employees 
        ON Employees.id = (
            CoursesEmployees.employee_id
        ) 
INNER JOIN
    courses Courses 
        ON Courses.id = (
            CoursesEmployees.course_id
        ) 
WHERE
    (
        CoursesEmployees.completed = 1 
        AND Employees.user_id = '1'
    ) LIMIT 20 OFFSET 0

【问题讨论】:

  • 额外的查询与您的 order-by 问题无关。 (or any random text for the field name - 这听起来像是白​​名单的原因 - 这是modified recently。请清理问题以专注于“问题”并澄清它是特定于分页的,问题的标题和正文目前颇具误导性。

标签: cakephp cakephp-3.0


【解决方案1】:

如果您立即重新运行脚本,您应该会看到这些查询消失。

这些查询用于获取数据以生成架构和其他元数据,默认情况下,由于数据正在缓存,这种情况很少发生,因为在您的应用数据源配置中启用了cacheMetadata

默认情况下,数据会缓存 2 分钟,请检查您的应用缓存配置中的 _cake_model_。这是应用程序在调试模式下运行时将使用的值。未处于调试模式时,持续时间默认设置为 1 年,请检查您的应用 boostrap.php

另见


至于您缺少订单字段的问题,您在白名单中缺少Employees.name 字段,但是即使将其他模型的字段列入白名单,它似乎也不起作用。

这似乎是分页器中的一个错误,即在 PaginatorComponent::_prefix() 方法中,该字段被吞噬,最终导致将空的 order 选项传递给查询。

看起来这已经被报告和fixed 用于即将发布的 3.0.7 版本。如果你迫不及待,请抓住主分支或应用补丁。

【讨论】:

  • 非常感谢您的洞察力 :-) 当我重新运行脚本时,确实只有一个查询。如果我将字段名称切换为 order by,则多个查询会在第一次加载时再次出现。但是,如果我使用 Models.field,我的问题仍然存在,我在查询中没有得到 order by。我刚收到LIMIT 20 OFFSET 0
  • @KeithPower 我必须管理我只浏览了文本,稍后我会再看看你的问题。
  • 谢谢,我可能会通过提及额外的查询而不是 order by 在关联表上的查询中丢失来混淆问题
  • 只是一个小提示,如果我接受查询并将ORDER BY Employees.name 添加到末尾并直接在数据库中运行sql,我会得到预期的结果。
  • @KeithPower 是的,这是意料之中的。我再次使用修复链接更新了我的答案。
猜你喜欢
  • 2018-04-05
  • 1970-01-01
  • 2011-10-03
  • 2018-01-21
  • 1970-01-01
  • 1970-01-01
  • 2012-10-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多