返回

如何解决 CakePHP 中 HABTM 关系和翻译查询时无法获取翻译字段的问题?

php

如何使用 HABTM 关系和翻译查询 CakePHP 中的数据

简介

在使用 CakePHP 时,你可能会遇到一个问题:无法在查询 HABTM 关系时获取翻译字段。这篇文章将为你提供一个解决方案,使用 Containable 行为和翻译模型来解决这个问题。

背景

假设你有以下模型设置:

Client 模型

public $belongsTo = array("User");
public $hasAndBelongsToMany = array(
    'Category' =>
        array(
            'className' => 'Category',
            'joinTable' => 'categories_clients',
            'foreignKey' => 'client_id',
            'associationForeignKey' => 'category_id',
            'unique' => true,
        ),
);

Category 模型

public $name = 'Category';
public $hasMany = array(
    'Product'
);
public $displayField = 'title';
public $recursive = 1;
public $actsAs = array(
    'Tree',
    'Translate' => array(
        'title', 
        'alias', 
        'description',
    ),
    'Containable' => array('CategoryTranslations'),
);
public $translateModel = 'CategoryTranslations';
public $translateTable = 'category_translations';

问题

当你尝试从 Client 控制器查询 Client 和相关的 Category 时,你无法获取 Category 的翻译字段。

解决方案:使用 Containable 行为

要解决此问题,需要使用 Containable 行为。它允许你在查询 Client 模型时从 Category 模型中获取翻译字段。

修改后的代码如下:

    if(isset($this->passedArgs['language_id'])){
        $language_id = $this->passedArgs['language_id'];
    }
    else{
        $language_id = Configure::read('Config.language_site');
    }
    $this->Client->Category->locale = $language_id;
    $this->Client->Category->bindModel(array(
        'hasMany' => array(
            'CategoryTranslation' => array(
                'className' => 'CategoryTranslation',
                'foreignKey' => 'category_id',
                'conditions' => array('CategoryTranslation.language_id' => $language_id)
            )
        )
    ));
    $this->Client->recursive = 1;
    $this->paginate = array('limit' => 20,'order' => array('User.id' => 'desc'));
    $Clients = $this->paginate();

此代码绑定了 CategoryTranslation 模型,它包含翻译字段。通过指定语言 ID,你确保只获取与当前语言相对应的翻译。

现在,你可以访问翻译字段,如下所示:

foreach ($Clients as $client) {
    foreach ($client['Category'] as $category) {
        echo $category['CategoryTranslation']['title'];
        echo $category['CategoryTranslation']['alias'];
        echo $category['CategoryTranslation']['description'];
    }
}

结论

通过使用 Containable 行为,你可以在查询 HABTM 关系时获取翻译字段。这使你能够在应用程序中使用翻译数据,从而增强用户体验和国际化支持。

常见问题解答

  1. 什么是 HABTM 关系?
    HABTM(has and belongs to many)关系是一种数据库关系类型,它允许一个模型与多个其他模型相关联,反之亦然。

  2. 什么是 Containable 行为?
    Containable 行为允许你在查询一个模型时获取与该模型相关联的其他模型的数据。

  3. 如何绑定翻译模型?
    你可以使用 bindModel() 方法来绑定翻译模型,如下所示:

    $this->Model->bindModel(array(
        'hasMany' => array(
            'Translation' => array(
                'className' => 'Translation',
                'foreignKey' => 'model_id',
                'conditions' => array('Translation.language_id' => $language_id)
            )
        )
    ));
    
  4. 如何在模板中访问翻译字段?
    你可以使用以下语法在模板中访问翻译字段:

    echo $this->Model->Translation['field_name'];
    
  5. 如何处理多语言网站?
    在多语言网站中,你应该使用语言 ID 来指定要获取的翻译版本。