How to query translated content when using the translate behavior?

て烟熏妆下的殇ゞ 提交于 2019-12-02 03:08:17

问题


My website is in multiple languages so an article's title depends on the local. But there's a problem: How can I search for an article in another language?

Right now, the only way is by typing the title in english so that cakePHP retrieves the name in french, for exmple. I can't search for it in french.

For exemple: When I search for "Hello" I find the article named "Bonjour" But when I search for "Bonjour" I can't find any article.

So how do I search in another language? It seem that Cakephp search first in default language to then get the traductions.

In my controller:

$this->Ingredients->locale('fr_CA');
$data = $this->Ingredients->find('all')
->select([
    'Ingredients.id',
    'Ingredients.name'
])
->where(["Ingredients.name LIKE '%".$this->request->query['k']."%'"])
->order('Ingredients.recipe_count');

回答1:


SQL Injections!

First things first, what you have there is a SQL injection vulnerability, as you are inserting user data into an SQL fragment instead of using the key => value format, which would result in proper queries with bound values!

Please be sure to read Cookbook > Database Access & ORM > Query Builder > Advanced Conditions for more information on how to properly build advanced conditions!

Searching translated content

Searching by translated content, well, the Translate behavior adds a hasOne association for each translatable field, and by default the naming scheme is TableAlias_field_translation, so for example Ingredients_name_translation.

The association is being contained automatically, so you can search on its content field, which will possibly hold the translated content.

As of CakePHP 3.4.0, respectively 3.4.4, you can use the translationField() method provided by the translate behavior, it will return the properly aliased field depending on the locale:

->where([
    $this->Ingredients->translationField('name') . ' LIKE' =>
        '%' . $this->request->query('k') . '%'
])

Note that before 3.4.4, translationField() would not consider the case where the locale set matches the default locale! In that situation you would want to query against the original tables name column, but before 3.4.4 the method would always return the content column of the associated translation table.

See also Cookbook > Database Access & ORM > Behaviors > Translate > Querying Translated Fields

In versions before CakePHP 3.4, you'll have to build the column name yourself, like:

->where([
    'Ingredients_name_translation.content LIKE' => '%' . $this->request->query['k'] . '%'
])

In the case mentioned above, where the locate set matches the default language, the Translate behavior won't contain the translation table associations, so you'd have to take appropriate measures to ensure that the correct field is being used in the conditions, based on the language in use, ie use Ingredients.name in case the default language is being used!



来源:https://stackoverflow.com/questions/31495745/how-to-query-translated-content-when-using-the-translate-behavior

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!