将新的可翻译字段添加到CakePHP 2.2中的现有可翻译表中

时间:2012-11-06 03:10:36

标签: cakephp cakephp-2.0 cakephp-2.1 cakephp-2.2

我正在使用CakePHP的可翻译行为。我有一些现有的字段工作正常,但我在为我的模型添加一个新的可翻译字段时遇到了麻烦。

CakePHP使用INNER JOIN从数据库中获取所有可翻译字段。

现在,如果我在模型中添加一个额外的可翻译字段,那么该字段的所有翻译记录都不会存在于数据库中。并且由于内部联接,每当它尝试从数据库中获取任何现有记录时,它将返回空白 - 因为新字段上的INNER JOIN失败,因此整个查询不返回任何内容。

以前人们肯定会遇到这种情况。有一个简单的解决方案吗?

一种解决方案是编辑/覆盖核心并使所有INNER JOIN进入LEFT OUTER JOIN。那有什么不对吗?

另一种解决方案是在翻译表上运行更新,以便在每次添加新的可翻译字段时为新字段创建所有额外记录 - 但我讨厌该解决方案。

有更好的解决方案吗?别人怎么处理这个问题?

提前致谢。

1 个答案:

答案 0 :(得分:0)

好的,这是在每次添加新的可翻译字段后确保记录存在的方法。如果您有更好的答案,请添加它,我会将您的答案标记为正确。

PS - 这是为了我的目的进行测试。我正在使用多个翻译表(http://book.cakephp.org/2.0/en/core-libraries/behaviors/translate.html#multiple-translation-tables)。我认为它应该适用于大多数情况,但如果没有,它至少应该是一个很好的起点。

在您的模型(作为可翻译的模型)中,添加以下方法。它所做的是获取一系列语言环境,然后对于表中的每个记录,以及每个可翻译字段,以及每个语言环境(即3个循环),它检查是否存在翻译记录。如果翻译不存在,则会添加一个空白翻译,因此至少INNER JOIN不会失败。

它返回它添加的所有记录的数组,因此您可以检查它们或更改它们的内容等等。

这是模型方法:

function ensureTranslationIntegrity($localesToCheck){
    $allRows = $this->find('all', array('fields' => array('id')));
    $fieldsToCheck = array();

    $translatableFields = $this->actsAs['Translate'];
    foreach($translatableFields as $key => $value){
        // actsAs Translatabe can take field names only, or Key => Value pairs - see http://book.cakephp.org/2.0/en/core-libraries/behaviors/translate.html#retrieve-all-translation-records-for-a-field
        if(is_numeric($key)){
            $field = $value;
        } else {
            $field = $key;
        }
        array_push($fieldsToCheck, $field);
    }

    $translateModel = $this->translateModel();
    $addedRows = array(); // This will contain all the rows we have to add

    foreach ($allRows as $row){
        foreach($fieldsToCheck as $field){
            foreach($localesToCheck as $locale){
                $conditions = array(
                    'model' => $this->name,
                    'foreign_key' => $row[$this->name]['id'],
                    'field' => $field,
                    'locale' => $locale
                );
                $translation = $translateModel->find('first',array('conditions' => $conditions));

                if(!$translation){
                    $data = $conditions; // The data we want to insert will mostly just match the conditions of the failed find
                    $data['content'] = ''; // add it as empty

                    $translateModel->create();
                    $translateModel->save($data);

                    array_push($addedRows, $data);
                }
            } // END foreach($localesToCheck as $locale){
        } // END foreach($fieldsToCheck as $field){
    } // END foreach ($allRows as $row){

    return $addedRows;
}

在你的控制器中,你会这样称呼它:

public function ensure_translation_integrity(){
    $locales = array('en_au','en_gb','en_nz','pt_br','xh_za');
    $addedRows = $this->YourModel->ensureTranslationIntegrity($locales);
    debug($addedRows);
}

希望能帮到某个人,但就像我说的那样,如果有人,我希望能找到更好的解决方案。