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()
метод, гарантирующий, что используется правильное поле в зависимости от текущей установленной локали.
Смотрите также