В ситуациях, когда необходимо совершать действия над таблицей, которая уже содержит в себе какие-либо данные, может возникнуть неприятная ошибка: "Mysql error 1452 - Cannot add or update a child row: a foreign key constraint fails".
Возникает она вследствие того, что мы пытаемся изменить существующую запись таким образом, что нарушается целостность.
Например, присвоение полю ключа, который не существует в родительской таблице. Или создание нового внешнего ключа для поля, которое не должно быть NULL, в таблице, которая уже содержит некоторое количество записей. Последняя проблема у меня и возникла. Необходимо было решение, и оно было найдено.
Решение простое как пять копеек. Нам необходимо избавиться от NULL-значений в поле, на которое навешивается внешний ключ.
Предположим, что вы уже отредактировали схему соответствующим образом и она имеет примерно следующее содержание:
Human: columns: name: { type: string(255), notnull: true } human_status_id: { type: integer, notnull: true } relations: HumanStatus: local: human_status_id foreign: id onDelete: CASCADE HumanStatus: columns: name: { type: string, notnull: true }
После успешной генерации миграций должны появиться два файла миграций: один будет содержать создание таблиц, а вторая создание связей между ними. Именно второй файл мы и будем редактировать. Нам это никто не запрещает.
Итак, как я уже сказал, нам необходимо избавиться от NULL-значений. Для этого мы поправим вторую миграцию примерно таким образом:
public function up() { $conn = Doctrine_Manager::getInstance()->getCurrentConnection(); $oHumanStatus = new HumanStatus(); $oHumanStatus->setName('Temp'); $oHumanStatus->save(); Doctrine_Query::create() ->update() ->from('Human') ->set('human_status_id', $oHumanStatus->getId()) ->execute(); $this->createForeignKey('human', 'human_human_status_id_human_status_id', array( 'name' => 'human_human_status_id_human_status_id', 'local' => 'human_status_id', 'foreign' => 'id', 'foreignTable' => 'human_status', 'onUpdate' => '', 'onDelete' => 'CASCADE', )); $this->addIndex('human', 'human_human_status_id', array( 'fields' => array( 0 => 'human_status_id', ), )); }
Думаю, основная идея понятна. Если нет нужды в создании новой записи в таблице HumanStatus, можно поискать уже существующие. Все зависит от вашей ситуации.
Далее накатываем обе миграции. Все должно пройти успешно. Если нет — читайте мануалы дальше. Возможно, это не ваш случай.
P.S. Не оставляйте die() в up() или down() методах миграции. Иначе она не накатится.