Текущая модель несовместима со старыми миграциями - PullRequest
0 голосов
/ 10 апреля 2019

У меня есть следующая позиция (я опишу ее как строку истории):

  1. Я настраиваю проект с User моделью (и users таблицей) с файлом миграции A
  2. Через некоторое время я добавляю таблицу user_modules многие-ко-многим, и я был вынужден инициализировать этот массив во время обновления schama в файле миграции B . Я делаю это

    User::chunk(100, function($users) {
        foreach ($users as $user) {
            $user->userModule()->create();
        }
    });
    
  3. Через некоторое время мне нужно обновить User модель и таблицу, добавив soft-delete (столбец delete_at) в файле миграции C и поле $dates=['deleted_at'] в User модели.
  4. Затем я разрабатываю систему и добавляю больше миграций, но в какой-то момент к нашей команде присоединяется новый разработчик, и он должен создать схему БД с нуля, чтобы запустить php artisan:migrate, но он получил ошибку в файле миграции B :

[Осветить \ База данных \ QueryException (42S22)]
SQLSTATE [42S22]: столбец не найден: 1054 столбец неизвестен 'users.deleted_at' в 'предложении where' (SQL: выберите * из users где users. deleted_at - нулевой порядок на users. id asc limit 100 выключено 0)

То есть текущая User модель несовместима с файлом миграции B

Как справиться с этой ситуацией?

Где я допустил ошибку и что нужно сделать, чтобы предотвратить такую ​​ситуацию в будущем?

Ответы [ 2 ]

3 голосов
/ 10 апреля 2019

Это из-за Soft Deletes.Когда вы добавляете признак SoftDeletes в модель, он автоматически добавляет where users.deleted_at is null ко всем запросам.Лучший способ обойти это - добавить withTrashed() к вашему запросу в миграции B.

Для этого измените запрос в миграции B, чтобы он выглядел следующим образом.Это должно удалить часть, где он пытается получить доступ к несуществующему столбцу deleted_at.Эта миграция, в конце концов, не знает, что вы хотите добавить мягкие удаления позже, поэтому имеет смысл иметь доступ ко всем пользователям, включая тех, которые были выброшены.

User::withTrashed()->chunk(100, function($users) {
    foreach ($users as $user) {
        $user->userModule()->create();
    }
});

Вы всегда можете закомментировать SoftDeleteперед запуском миграции также следует учитывать особенности пользовательской модели, но это временное исправление, поскольку вам нужно будет объяснить это всем будущим разработчикам.Кроме того, иногда очень удобно запускать php artisan migrate:fresh.Вам не нужно помнить, чтобы каждый раз комментировать черту, поэтому добавление withTrashed() кажется мне наиболее желательным решением.

В качестве последнего замечания я настоятельно рекомендую НЕ добавление семян в ваши миграции.Миграции должны ONLY использоваться для изменений схемы.В подобных случаях я бы использовал консольную команду или комбинацию консольных команд.

Например, вы можете создать консольную команду, которая запускается с помощью php artisan check:user-modules.Внутри этой команды вы можете иметь следующее, что создаст пользовательский модуль, только если он еще не существует.

User::chunk(100, function($users) {
    foreach ($users as $user) {
        if (!$user->userModule()->exists()) {
            $user->userModule()->create();
        }
    }
});

Вы сможете запускать эту команду в любое время, так как она не будет перезаписывать существующий.пользовательские модули.

0 голосов
/ 23 апреля 2019

Альтернативный ответ: В такой ситуации, когда нам нужно сгенерировать или преобразовать некоторые данные после изменения схемы БД - нам НЕ следует использовать Модели (которые могут изменяться независимо в будущем), а вместо этого использовать insert / обновления

DB::table('users')->chunkById(100, function ($users) {
    foreach ($users as $user) {
        DB::table('user_modules')->insert(
            ['user_id' => $user->id, 'module_id' => 1]
        );
    }
});

Как написано в документации laravel , сеялки предназначены для заполнения данных тестовыми данными, но не для преобразования данных, поэтому файлы миграции, вероятно, являются хорошим местом для размещения кода преобразования (который может генерировать или изменять некоторые данные). производственные данные в БД после обновления схемы)

Laravel включает в себя простой метод заполнения базы данных тестовыми данными с использованием начальных классов.

...