Можно ли использовать find ('list') с контейнерным поведением в Cake PHP 3? - PullRequest
0 голосов
/ 10 марта 2020

Приложение использует Cake PHP версия 3.5.18

Я использовал ORM для получения списка, который возвращает пары ключ / значение:

$Displays = TableRegistry::get('Displays');
$displays = $Displays->find('list', ['keyField' => 'id', 'valueField' => 'id'])->where(...)->toArray();

Это работает, как и ожидалось. Пример debug($displays); выглядит следующим образом:

(int) 36 => (int) 36,
(int) 160 => (int) 160,
(int) 149 => (int) 149,
...

В этом конкретном приложении есть 3 модели, которые работают в следующей иерархии:

  • Правила (Уровень 1. Название таблицы regulations)
    • Группы (Уровень 2. Имя таблицы groups)
      • Дисплеи (Уровень 3. Имя таблицы displays)

Приложение запечено так, что в классах таблицы определены соответствующие отношения.

// src/Model/Table/RegulationsTable.php
$this->hasMany('Groups', [
    'foreignKey' => 'regulation_id'
]);

// src/Model/Table/GroupsTable.php
$this->hasMany('Displays', [
    'foreignKey' => 'group_id'
]);

// src/Model/Table/DisplaysTable.php
$this->belongsTo('Groups', [
    'foreignKey' => 'group_id',
    'joinType' => 'INNER'
]);

Я хочу настроить запрос, определенный $displays, так что что результаты соответствуют данному массиву Regulations.id. Ванильный SQL эквивалент того, что я пытаюсь сделать, это ... WHERE regulations.id IN (1,2,3) при условии, что идентификаторы были 1, 2 и 3.

Когда я читаю документы Cake по Условия прохождения содержат он говорит:

Когда вы ограничиваете поля, извлекаемые из ассоциации, вы должны убедиться, что выбраны столбцы внешнего ключа. Отказ от выбора полей внешнего ключа приведет к тому, что связанные данные не будут присутствовать в конечном результате.

Я не понимаю, как это возможно с find('list'), потому что это выбирает только keyField и valueField указано разработчиком? В этом случае это будет displays.id для обоих.

В любом случае я не понимаю, как написать этот запрос, потому что в той же связанной документации написано

При использовании contain() вы можете ограничить данные, возвращаемые ассоциации и фильтровать их по условиям. Чтобы указать условия, передайте анонимную функцию, которая получает в качестве первого аргумента объект запроса, \Cake\ORM\Query

На что в действительности будет действовать contain(): я предполагаю, что это Regulations, но не знаю, как это написать.

1 Ответ

1 голос
/ 10 марта 2020

Я думаю, вам нужно смотреть на фильтрацию данных по соответствию, а не по содержанию. (Если я правильно понимаю.)

Вы можете объединить find('list') с ->matching(...):

$displays = $this->Displays->find('list')
    ->matching('Groups.Regulations', function ($q) use ($ids) {
        return $q->where(['Regulations.id IN' => $ids]);
    })
    ->toArray();

(все еще не проверено)

...