CakePHP 3.4.7 - Как запросить переведенный контент в содержащихся ассоциациях?

Я обновил CakePHP до версии CakePHP 3.4.7. Мой сайт на нескольких языках, поэтому заголовок комментария и автора зависит от местного. Как запросить переведенный контент в содержавшихся ассоциациях? PHP-код в контроллере выглядит так:

//Comments belongsTo Authors     
$this->loadModel('Comments');
    $comments = $this->Comments->find('all')->where(['Comments.active' => 1])->contain([
    'Authors' => function ($q) {
       return $q
            ->where(['Authors.title LIKE' => '%'.$this->term.'%','Authors.active' => 1])
            ->order(['Authors.position' => 'ASC']);
     }
     ])->toArray();

Это работает только для языка по умолчанию, но когда я меняю язык, я всегда получаю пустой массив. Таблица i18n содержит записи для "комментариев" и "авторов" на других языках. В "авторской" модели:

$this->addBehavior('Translate', ['fields' => ['title','text']]);

Когда я изменил код в соответствии с примером: Как запросить переведенный контент при использовании поведения перевода? Я получил следующие результаты:

//Authors hasMany Comments - IT WORKS!!!
$this->loadModel('Authors');
$authors = $this->Authors->find('all')->where(['Authors.active' => 1])->contain([
'Comments' => function ($q) {
   return $q
        ->where(['Comments_title_translation.content LIKE' => '%'.$this->term.'%','Comments.active' => 1])
        ->order(['Comments.position' => 'ASC']);
 }
 ])->toArray();

//Comments belongsTo Authors  - IT DOES NOT WORK!!! 
$this->loadModel('Comments');
$comments = $this->Comments->find('all')->where(['Comments.active' => 1])->contain([
 'Authors' => function ($q) {
   return $q
        ->where(['Authors_title_translation.content LIKE' => '%'.$this->term.'%','Authors.active' => 1])
        ->order(['Authors.position' => 'ASC']);
 }
 ])->toArray();

На самом деле моя проблема - второй пример // Комментарии принадлежат авторам Отображается следующая ошибка: Ошибка: SQLSTATE[42S22]: Столбец не найден: 1054 Неизвестный столбец 'Authors_title_translation.content' в 'on' предложении '

1 ответ

Решение

Проблема заключается в порядке создания соединений, это работает для hasMany ассоциация, так как эта ассоциация извлекается в отдельном запросе, и LIKE условие применяется непосредственно в WHERE пункт этого запроса.

В случае belongsTo ассоциации, связанная таблица объединяется в основной запрос, и условия, переданные в contain конфигурация применяется в соединениях ON Предложение, которое происходит до определения соединения для таблицы перевода, следовательно, ошибка.

Вместо этого вы можете применить условия к основному запросу:

$this->Comments
    ->find('all')
    ->where([
        $this->Comments->Authors->translationField('title') . ' LIKE' =>
            '%' . $this->term . '%',
        'Authors.active' => 1,
        'Comments.active' => 1
    ])
    ->contain([
        'Authors' => function ($q) {
            return $q->order(['Authors.position' => 'ASC']);
        }
    ])
    ->toArray();

или измените на select или subquery стратегия получения связанных данных. В обоих случаях соответствующие данные будут получены в отдельном запросе, а условия будут применены в WHERE пункт:

$this->Comments
    ->find('all')
    ->where(['Comments.active' => 1])
    ->contain([
        'Authors' => [
            'strategy' => \Cake\ORM\Association::STRATEGY_SELECT,
            'queryBuilder' => function ($q) {
                return $q
                    ->where([
                        $this->Comments->Authors->translationField('title') . ' LIKE' =>
                            '%' . $this->term . '%',
                        'Authors.active' => 1
                    ])
                    ->order(['Authors.position' => 'ASC']);
            }
        ]
    ])
    ->toArray();

Как уже упоминалось в комментариях, вы должны в любом случае использовать варианты перевода translationField() метод, гарантирующий, что используется правильное поле в зависимости от текущей установленной локали.

Смотрите также

Другие вопросы по тегам