2011-01-17 4 views
4

우리는 doctrine 마이그레이션을 사용하고 있으며 마이그레이션에 여러 작업이 포함되어 있고 그 중 하나가 실패 할 때 종종 문제가 발생합니다.Doctrine 마이그레이션 fallback

예를 들어,이 5 외래 키를 추가 마이그레이션과 필드가없는 같은 길이의 동안 그들 중 5는 필드 오류를 수정, 실패하고 마이그레이션을 재생하는 하지 모든 일을 해결 않는 경우, 현재 키의 4 개가 이미 존재하므로 이주가 성공적으로 실행되지 않는 오류가 있습니다.

언급 된 명백한 문제없이 Doctrine 마이그레이션을 안정적으로 사용할 수 있습니까? 우리는 .sql 파일을 previosly로 사용했습니다. 실제로는별로 좋지는 않지만, Doctrine을 사용하는 프로젝트의 데이터베이스 버전 관리 방법은 무엇입니까?

모델과 스키마의 차이점을 기반으로 마이그레이션을 생성하는 것이 좋습니다.이 가능성을 더욱 높게 유지하고 싶습니다.

감사합니다.

답변

2

사용할 수있는 명령의 목록에 표시되며,이 솔루션은 모든 좋은 것이 아니라 여전히 것 같아요 그것은 다른 사람들에게 유용 할 것입니다. 저는 실제로 CLI를 사용하고 있습니다. 이미 모든 마이 그 레이션을 데이터베이스의 번호로 업데이트 한 파일을 작성했습니다.이 질문을하기 전에 티모의 대답과 유사하지만 여전히 효과적이지는 않지만 어쨌든 가치가 있습니다.

다음 해결 방법은 doctrine/lib/Doctrine/Migration/Builder.php 행 531입니다. 마이그레이션 할 때마다 기본 클래스의 정의가 있습니다. CLI를 사용하고있어 매개 변수를 전달하는 방법을 찾지 못했기 때문에 아래에 다른 클래스 MY_Doctrine_Migration_BaseDoctrine_Migration_Base으로 바 꾸었습니다.

CLI를 사용하지 않는 경우 옵션을 전달하고 소스를 바꾸지 말아야한다고 말하고 싶습니다.

따라서 아래 클래스는 Doctrine_Migration_Base을 확장하고 여러 메서드를 덮어 씁니다. 변경을 확인한 다음 부모 메서드를 호출하여이를 수행하는지 확인합니다. 그것은 현재 모든 방법을 다루지는 않습니다. 내가 이것을 썼을 때 내가 만났던 것입니다.

이제 모든 마이그레이션 Doctrine은 원래 언급 한 문제를 방지하기위한 클래스 확장을 만듭니다.

<?php 

class MY_Doctrine_Migration_Base extends Doctrine_Migration_Base { 
    public function __construct() { 
     $this->connection = Doctrine_Manager::getInstance()->getCurrentConnection(); 
    } 

    public function addIndex($tableName, $indexName, array $definition) { 
     foreach ($this->connection->execute("SHOW INDEXES IN $tableName")->fetchAll(PDO::FETCH_ASSOC) as $index) { 
      if ($index['Key_name'] === $indexName.'_idx') { 
       echo "Index $indexName already exists in table $tableName. Skipping\n"; 
       return; 
      } 
     } 

     parent::addIndex($tableName, $indexName, $definition); 
    } 

    public function removeColumn($tableName, $columnName) { 
     if ($this->column_exists($tableName, $columnName)) { 
      parent::removeColumn($tableName, $columnName); 
     } else { 
      echo "Column $columnName doesn't exist in $tableName. Can't drop\n"; 
     } 
    } 

    public function createTable($tableName, array $fields = array(), array $options = array()) { 
     if ($this->connection->execute("SHOW TABLES LIKE '$tableName'")->fetchAll(PDO::FETCH_ASSOC)) { 
      echo "Table $tableName already exists. Can't create\n"; 
     } else { 
      parent::createTable($tableName, $fields, $options); 
     } 
    } 

    public function addColumn($tableName, $columnName, $type, $length = null, array $options = array()) { 
     if (! $this->column_exists($tableName, $columnName)) { 
      parent::addColumn($tableName, $columnName, $type, $length, $options); 
     } else { 
      echo "Column $columnName already exists in $tableName. Can't add\n"; 
     } 
    } 

    private function column_exists($tableName, $columnName) { 
     $exception = FALSE; 

     try { //parsing information_schema sucks because security will hurt too bad if we have access to it. This lame shit is still better 
      $this->connection->execute("SELECT $columnName FROM $tableName")->fetchAll(PDO::FETCH_ASSOC); 
     } catch (Exception $exception) {} 
     //if someone knows how to check for column existence without exceptions AND WITHOUT INFORMATION SCHEMA please rewrite this stuff 

     return $exception === FALSE; 
    } 
} 

개선 방법에 대한 제안을 환영합니다.

0

Doctrine 마이그레이션에서 처리하지 못합니다. 유감스럽게도 마이그레이션에서 트랜잭션이 실행되지 않았기 때문에 우리 모두에게 이러한 문제가 있다고 말할 수 있습니다.

플러그인을 추가하면이 기능을 향상시킬 수 있습니다. 참조 : Blog-Post

다른 가능성은 마이그레이션하기 전에 데이터베이스 백업을 수행하는 것이므로 문제가 발생하면 백업을 다시 설치할 수 있습니다. 쉘 스크립트로 이것을 자동화 할 수 있습니다

1

doctrine-cli를 사용하는 경우 마이그레이션 전에 데이터베이스를 백업하고 마이그레이션이 실패 할 경우 백업을 복원하는 고유 한 마이그레이션 작업을 작성할 수 있습니다. 나는 symfony/doctrine 마이그레이션과 비슷한 것을 썼다.

올바른 디렉토리에 작업 클래스를 넣으면 교리의 CLI는 내가 가지이 문제를 해결