【问题标题】:Add a new translatable field to an existing translatable table in CakePHP 2.2在 CakePHP 2.2 中向现有的可翻译表添加一个新的可翻译字段
【发布时间】:2012-11-06 03:10:36
【问题描述】:

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

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

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

肯定有人以前遇到过这种情况。有没有简单的解决方案?

一种解决方案是编辑/覆盖核心并将所有 INNER JOIN 变成 LEFT OUTER JOIN。这有什么问题吗?

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

有没有更好的解决方案?其他人是如何处理这个问题的?

提前致谢。

【问题讨论】:

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


    【解决方案1】:

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

    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);
    }
    

    希望对某人有所帮助,但就像我说的那样,如果有人有更好的解决方案,我很乐意看到。

    【讨论】:

      猜你喜欢
      • 2017-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多