Как фильтровать связанные данные с помощью плагина FriendsOfCake Search для CakePHP 3.1.0

Плагин: FriendsOfCake\Search

CakePHP: 3.1.0

В настоящее время я добавляю возможность фильтровать мой контроллер заказов по методу index(). Мне нужно иметь возможность искать заказы по имени пользователя, разместившего заказ. Каждый заказ связан с моделью Users:

    $this->belongsTo('Users', [
        'foreignKey' => 'user_id',
        'joinType' => 'INNER'
    ]);

Когда я создаю свой searchConfiguration() метод в OrdersTable.php файле, я получаю следующее:

    ->value('first_name', [
        'field' => $this->aliasField('Users.first_name')
    ])
    ->value('last_name', [
        'field' => $this->aliasField('Users.last_name')
    ])

Метод Orders index ()

    $query = $this->Orders->find('search', 
        $this->Orders->filterParams($this->request->query))->contain(['Users', 'PaymentMethods', 'Industries']
    )->order(['Orders.created' => 'DESC']);
    $this->set('orders', $this->paginate($query));

Это нормально загружается, когда я не передаю никаких параметров в запрос, однако, как только я пытаюсь выполнить поиск по first_name или last_name, я получаю сообщение об ошибке:

Ошибка: SQLSTATE [42S22]: столбец не найден: 1054 Неизвестный столбец "Orders.Users.first_name" в предложении where

В зависимости от ошибки он добавляет заказы. в поле, по которому я пытаюсь выполнить поиск. Насколько я могу судить, CakePHP имеет 2 метода aliasField() один в \var\www\<project_name>\vendors\cakephp\cakephp\src\ORM\Query.php

public function aliasField($field, $alias = null)
{
    $namespaced = strpos($field, '.') !== false;
    $aliasedField = $field;

    if ($namespaced) {
        list($alias, $field) = explode('.', $field);
    }

    if (!$alias) {
        $alias = $this->repository()->alias();
    }

    $key = sprintf('%s__%s', $alias, $field);
    if (!$namespaced) {
        $aliasedField = $alias . '.' . $field;
    }

    return [$key => $aliasedField];
}

И один из \var\www\<project_name>\vendors\cakephp\cakephp\src\ORM\Table.php

public function aliasField($field)
{
    return $this->alias() . '.' . $field;
}

Похоже, что Query.php позволит вам указать $alias для поля, однако Table.php этого не делает, поэтому я предполагаю, что это метод, который здесь используется.

Может ли кто-нибудь дать мне руководство о том, как фильтровать данные, содержащиеся в связанной таблице?


person hulk66049    schedule 26.10.2015    source источник


Ответы (1)


Просто либо не используйте aliasField(), если вы уже указываете псевдоним

'field' => 'Users.first_name'

или используйте aliasField() в связанной Users таблице

'field' => $this->Users->target()->aliasField('first_name')

Использование Query::aliasField() было бы совершенно неправильным, так как это вернет массив key => value для использования с Query::select().

person ndm    schedule 27.10.2015
comment
Использование приведенного выше кода отлично сработало. У меня есть 2 вопроса. 1. Когда я впервые изменил свой код, я оставил - ›target () вне строки, и он тоже работал. Какую цель обеспечивает метод target ()? 2. Вы упомянули, что при предоставлении псевдонима не использовали aliasField (), как бы мне это закодировать? - person hulk66049; 28.10.2015
comment
@ hulk66049 1.) Использование target() более конкретно. Он работает и без него, потому что внутренне класс ассоциации (свойство Users не содержит экземпляр класса таблицы!) Будет делегировать вызовы неизвестных методов target() с использованием волшебного обработчика __call(). 2.) См. Мой обновленный ответ. - person ndm; 28.10.2015