Почему CakePHP дублирует мои запросы?(это не та проблема "слишком много запросов", которая обычно задается) - PullRequest
1 голос
/ 20 октября 2010

Я определил эти отношения в моих моделях:

Ведущий имеет много работы
Работа HABTM Сотрудник
Работа HABTM Truck

Я пытаюсь сделать find('all') из моей модели Грузовика и ограничить результаты до:

  1. Все грузовики,
  2. все работы, связанные с теми грузовиками, которые имеют определенную дату вывоза,
  3. сотрудников, назначенных на эти рабочие места,
  4. и руководство, связанное с работой.

Вот моя операция поиска:

// app/models/truck.php
$this->find('all', array(
    'contain' => array(
        'Job' => array(
            'Employee',
            'Lead',
            'conditions' => array(
                'Job.pickup_date' => $date
            )
        )
    )
));

По какой-то причине Cake выполняет запрос, чтобы найти сотрудников ДВАЖДЫ. Это приводит к тому, что все сотрудники представлены по два раза на каждую работу. Вот дамп SQL:

  1. SELECT `Truck`.`id`, `Truck`.`truck_number`
    FROM   `trucks` AS `Truck`
    WHERE  1 = 1;
  2. SELECT `Job`.`id`, `Job`.`lead_id`, `Job`.`city`,
           `JobsTruck`.`id`, `JobsTruck`.`job_id`, `JobsTruck`.`truck_id`
    FROM   `jobs` AS `Job`
    JOIN   `jobs_trucks` AS `JobsTruck` ON (`JobsTruck`.`truck_id` IN (2, 3)
    AND    `JobsTruck`.`job_id` = `Job`.`id`)
    WHERE  `Job`.`pickup_date` = '2010-10-06'
  3. SELECT `Lead`.`id`, `Lead`.`name`, `Lead`.`created` FROM `leads` AS `Lead`
    WHERE  `Lead`.`id` = 4
  4. SELECT `Employee`.`id`, `Employee`.`name`, `Employee`.`created`,
           `EmployeesJob`.`id`, `EmployeesJob`.`employee_id`,
           `EmployeesJob`.`job_id`
    FROM   `employees` AS `Employee`
    JOIN   `employees_jobs` AS `EmployeesJob`
           ON (
               `EmployeesJob`.`job_id` = 1 AND
               `EmployeesJob`.`employee_id` = `Employee`.`id`
           )
  5. SELECT `Lead`.`id`, `Lead`.`name`, `Lead`.`created` FROM `leads` AS `Lead`
    WHERE  `Lead`.`id` = 4
  6. SELECT `Employee`.`id`, `Employee`.`name`, `Employee`.`created`,
           `EmployeesJob`.`id`, `EmployeesJob`.`employee_id`,
           `EmployeesJob`.`job_id`
    FROM   `employees` AS `Employee`
    JOIN   `employees_jobs` AS `EmployeesJob`
           ON (
               `EmployeesJob`.`job_id` = 1 AND
               `EmployeesJob`.`employee_id` = `Employee`.`id`
           )

Обратите внимание, что последние два запроса являются дубликатами. Я сделал что-то не так, что мне не хватает?

UPDATE
Кажется, Cake отправляет повторный запрос для каждого грузовика. Теперь, когда у меня 15 записей в таблице грузовиков, запросы к leads и employees дублируются по 15 раз каждый.

Ответы [ 3 ]

3 голосов
/ 21 ноября 2010

Я не знаю, почему дублируются два запроса, но, возможно, это поможет:

https://github.com/Terr/linkable

UPDATE

Такая проблема хорошо известна:

1 голос
/ 24 ноября 2010

Нет ничего, что могло бы присоединить найденное Job/s к определенному Truck.

(Надеюсь, мое объяснение не слишком сложно для понимания, но CakePHP иногда может быть таким! Imho)

Jobs приписывают Trucks почти произвольным образом (моя память о Cake такова, что это может произойти); природа вызова HABTM прикрепляет Job/s к каждому из 15 Trucks. Это, кажется, текущий процесс с моей точки зрения;

  • Получить все грузовики.
  • Получить все рабочие места для тех грузовиков, где дата x .
  • [Задача 1] Прикрепите найденные Jobs к каждому Truck (то есть вашим 15 грузовикам), но прикрепите к каждому Truck.
  • [Задача 2] Получить всех потенциальных клиентов / сотрудников, связанных с этой работой, снова для каждого Truck.

Проблема 1: источник проблемы. Вы можете видеть во втором запросе (SELECT Job ...), где он использует правильные truck_id в операторе ON, но Cake не может "соединить" эти Jobs обратно в правый Truck, потому что это другой запрос! Таким образом, он объединяет найденные вакансии с каждым Truck.

Проблема 2: Это «реальная» проблема, поскольку Cake не создает длинные операторы JOIN, поэтому нет способа найти Employees / Leads только для тех Trucks, которые вы хотите. Вот почему он находит их для каждого Грузовика, потому что вы делаете FindAll на Truck.

Надеюсь, это имеет смысл. Вам нужно найти все по Jobs, так как это 'center' запроса (pickup_date).

$this->loadModel('Job');
$whatev = $this->Job->find('all', array(
    'contain' => array(
        'Job' => array(
            'Truck',
            'Employee',
            'Lead',
            'conditions' => array(
                'Job.pickup_date' => $date
            )
        )
    )
));

Запросы CakePHP действительно работают только тогда, когда вы находите одну / всю определенную модель, лучше начинать с середины и работать с любой стороны, если у вас двойные отношения HABTM. Если вы хотите выполнить сортировку по Truck, то вам, возможно, придется написать собственный запрос (метод модели), чтобы выполнить задачу самостоятельно. В сыром SQL этот запрос может быть простым, в абстрактном супер-пироге PHP это трудно разрешить CakePHP.

Счастливой выпечки, как говорится!

0 голосов
/ 22 ноября 2010

Вы хотите LEFT JOIN вместо JOIN.

Не спрашивайте меня, как это сделать в cakephp, я рад, что мой код в настоящее время работает.^^

...