CakePHP 3: порядок переведенных данных с отсутствующими строками перевода - PullRequest
0 голосов
/ 26 апреля 2018

Я использую TranslationBehavior для обработки переведенных данных в моем приложении. При извлечении данных CakePHP возвращает переведенную строку или, если эта строка недоступна, значение локали по умолчанию. Для запроса данных используется следующий запрос:

$items = $this->Model->find('all')
  ->all()
  ->extract('name');

Чтобы заказать вывод, запрос:

$items = $this->Model->find('all')
  ->order([$this->Model->translationField('name') => 'ASC'])
  ->all()
  ->extract('name');

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

['A... (Translated)', 'B... (Translated)', 'A... (Default)', 'C... (Default)']

Что я ожидаю, так это следующий порядок:

['A... (Default)', 'A... (Translated)', 'B... (Translated)', 'C... (Default)']

Для этого я изменил запрос на:

$items = $this->Model->find('all')
  ->order(['IF('.$this->Model->translationField('name').' != "", '.$this->Model->translationField('name').', Model.name)' => 'ASC'])
  ->all()
  ->extract('name');

Что дает ожидаемый порядок:

['A... (Default)', 'A... (Translated)', 'B... (Translated)', 'C... (Default)']

Вопрос: это правильный способ обработки порядка смешанных локалей? Или я что-то упустил и CakePHP уже предлагает более простое решение?

Вы можете спросить, почему мы должны смешивать локали? В моем случае нет необходимости переводить все строки, потому что некоторые элементы идентичны на обоих языках.

1 Ответ

0 голосов
/ 04 мая 2018

Глядя на то, как CakePHP запрашивает переведенные поля и объединяет их позже на уровне PHP, это ожидаемое поведение, и вам действительно придется использовать условное выражение в предложении ORDER.

Я бы предложил использовать выражение CASE, так как функция IF() специфична для MySQL, что-то вроде:

$query = $this->Model->find();
$query
    ->orderAsc(
        $query->newExpr()->addCase(
            [
                $query->newExpr()->isNotNull($this->Model->translationField('name'))
            ],
            [
                $query->identifier($this->Model->translationField('name')),
                $query->identifier('Model.name')
            ]
        )
    )
    // ...

Что бы сгенерировать выражение, похожее на:

ORDER BY 
    CASE WHEN Model_name_translation.content IS NOT NULL
        THEN Model_name_translation.content
        ELSE Model.name END
    ASC

И как уже упоминалось в комментариях, если вы идете по маршруту " не переводить идентичные строки ", то вам следует избегать хранения пустых строк для таких "пропущенных" переводов, вместо этого не сохраняйте запись для их вообще.

Чтобы избежать всего этого, вы, конечно, можете добавить переводы для всего, даже если они одинаковы на разных языках.

...