2012-11-06 2 views
1

CakePHP의 번역 가능한 동작을 사용하고 있습니다. 기존 필드가 정상적으로 작동하지만 새 번역 가능 필드를 모델에 추가하는 데 문제가 있습니다.CakePHP 2.2의 기존 번역 가능 테이블에 새로운 번역 가능 필드 추가

CakePHP는 INNER JOIN을 사용하여 데이터베이스에서 모든 변환 가능한 필드를 가져옵니다.

이제 번역 가능한 필드를 모델에 추가하면 해당 필드에 대한 모든 번역 레코드가 데이터베이스에 존재하지 않게됩니다. 내부 조인 때문에 데이터베이스에서 기존 레코드를 가져 오려고 할 때마다 새 필드의 INNER JOIN이 실패하고 전체 쿼리가 아무것도 반환하지 않으므로 비어있게됩니다.

분명히 사람들은 전에 이런 상황에 처했을 것입니다. 쉬운 해결책이 있습니까?

한 가지 해결책은 핵심을 편집/덮어 쓰고 모든 내부 조인을 LEFT OUTER JOIN의 것으로 만드는 것입니다. 거기에 문제가 있습니까?

또 다른 솔루션은 번역 테이블에서 업데이트를 실행하여 새로운 번역 가능 필드를 추가 할 때마다 새 필드에 대한 모든 추가 레코드를 만드는 것입니다.하지만 그 솔루션은 싫습니다.

더 좋은 솔루션이 있습니까? 다른 사람들이이 문제를 어떻게 처리합니까?

미리 감사드립니다.

답변

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

희망 누군가가 도움이되지만 내가 말했듯이, 나는 좋겠 누군가가 있으면 더 나은 해결책을 보는 것을 좋아합니다.