Заполнение базы данных в файле миграции Laravel

67

Я просто изучаю Laravel и имею рабочий файл миграции, создающий таблицу пользователей. Я пытаюсь заполнить запись пользователя как часть переноса:

public function up()
{
    Schema::create('users', function($table){

        $table->increments('id');
        $table->string('email', 255);
        $table->string('password', 64);
        $table->boolean('verified');
        $table->string('token', 255);
        $table->timestamps();

        DB::table('users')->insert(
            array(
                'email' => '[email protected]',
                'verified' => true
            )
        );

    });
}

Но при запуске php artisan migrate появляется следующая ошибка:

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'vantage.users' doesn't exist

Это, очевидно, потому, что Artisan еще не создал таблицу, но вся документация, похоже, говорит о том, что существует способ использования Fluent Query для заполнения данных как часть миграции.

Кто-нибудь знает как? Спасибо!

Теги:
migration
mysql-error-1146

6 ответов

162
Лучший ответ

Не помещайте DB:: insert() внутри схемы Schema:: create(), потому что метод create должен закончить создание таблицы, прежде чем вы сможете вставить материал. Вместо этого попробуйте:

public function up()
{
    // Create the table
    Schema::create('users', function($table){
        $table->increments('id');
        $table->string('email', 255);
        $table->string('password', 64);
        $table->boolean('verified');
        $table->string('token', 255);
        $table->timestamps();
    });

    // Insert some stuff
    DB::table('users')->insert(
        array(
            'email' => '[email protected]',
            'verified' => true
        )
    );
}
  • 0
    Спасибо, Бенджамин, это отлично!
  • 1
    и как вставить несколько данных?
61

Я знаю, что это старый пост, но поскольку он появляется в поиске Google, я думал, что поделился бы некоторыми знаниями здесь. @erin-geyer отметил, что смешивание миграции и сеялки может создавать головные боли, а @justamartin противопоставляется тому, что иногда вам нужны/нужны данные, которые будут заполнены как часть вашего развертывания.

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

Тем не менее, по-прежнему сохраняется значение для разделения семян и миграции, поскольку это две связанные, но разные проблемы. Наша команда скомпрометировала создание миграций, которые называют сеялки. Это выглядит так:

public function up()
{
    Artisan::call( 'db:seed', [
        '--class' => 'SomeSeeder',
        '--force' => true ]
    );
}

Это позволяет вам запускать семя один раз, как перенос. Вы также можете реализовать логику, которая предотвращает или увеличивает поведение. Например:

public function up()
{
    if ( SomeModel::count() < 10 )
    {
        Artisan::call( 'db:seed', [
            '--class' => 'SomeSeeder',
            '--force' => true ]
        );
    }
}

Это, очевидно, условно выполнит вашу сеялку, если будет меньше 10 SomeModels. Это полезно, если вы хотите включить сеялку в качестве стандартной сеялки, которая выполняется при вызове artisan db:seed, а также при миграции, чтобы вы не "удвоились". Вы также можете создать обратную сеялку, чтобы откаты работали, как ожидалось, например,

public function down()
{
    Artisan::call( 'db:seed', [
        '--class' => 'ReverseSomeSeeder',
        '--force' => true ]
    );
}

Второй параметр --force требуется для запуска сеялки в рабочей среде.

  • 1
    Это, безусловно, лучший ответ. Поддерживаемый код, который разделяет проблемы!
  • 8
    Я бы внимательно рассмотрел долгосрочные последствия вызова сеялок из сценариев миграции. Версии сценариев переноса имеют дату / время, в то время как отправители обычно нет. В процессе разработки потребности в сеялках часто меняются, что приводит к возможности сценариев миграции с версией, которые запускают не версионные сеялки, что нарушает идепотентность. Другими словами, запуск одного и того же набора сценариев миграции изо дня в день может дать разные результаты.
Показать ещё 5 комментариев
10

Вот очень хорошее объяснение того, почему использование Laravel Database Seeder предпочтительнее использования Migrations: http://laravelbook.com/laravel-database-seeding/

Хотя, следуя инструкциям в официальной документации, это гораздо лучше, потому что реализация, описанная в приведенной выше ссылке, кажется, не работает и является неполной. http://laravel.com/docs/migrations#database-seeding

  • 1
    Я согласен с тобой, Эрин. Не смешивайте миграции с начальными данными, потому что весьма вероятно, что вы захотите заполнить некоторые данные в своей среде разработки, но не в своей производственной среде.
  • 12
    Хороший вопрос, но в некоторых ситуациях некоторые данные должны существовать в производственной среде. Например, должен существовать самый первый пользователь-администратор по умолчанию, чтобы клиент мог войти в систему в первый раз, должны существовать некоторые предустановленные роли авторизации, некоторые данные бизнес-логики также могут потребоваться немедленно. Таким образом, я думаю, что обязательные данные должны быть добавлены к миграциям (чтобы вы могли также увеличивать / уменьшать записи данных посредством отдельных миграций), но семена можно оставить для разработки.
Показать ещё 1 комментарий
3

Это должно делать то, что вы хотите.

public function up()
{
    DB::table('user')->insert(array('username'=>'dude', 'password'=>'z19pers!'));
}
  • 0
    Спасибо @ strings28, но ты видел, что я уже принял подобный ответ месяц назад?
  • 0
    Видимо, я не - извините :)
0

Другой простой способ сделать это - определить приватный метод, который создает экземпляр и сохраняет заинтересованную модель.

public function up()
{
    Schema::create('roles', function (Blueprint $table) {
        $table->increments('id');
        $table->string('label', 256);
        $table->timestamps();
        $table->softDeletes();
    });

    $this->postCreate('admin', 'user');
}

private function postCreate(string ...$roles)  {
    foreach ($roles as $role) {
        $model = new Role();
        $model->setAttribute('label', $role);
        $model->save();
    }
}

При таком решении поля меток времени будут генерироваться Eloquent.

РЕДАКТИРОВАТЬ: лучше использовать систему сеялки для различения структуры базы данных и заполнения базы данных.

  • 0
    Отлично, мне понравился твой подход. Спасибо
-9

попробуйте: (не проверено)

public function up()
{
    Schema::table('users', function($table){

        $table->increments('id');
        $table->string('email', 255);
        $table->string('password', 64);
        $table->boolean('verified');
        $table->string('token', 255);
        $table->timestamps();

        $table->insert(
            array(
                'email' => '[email protected]',
                'verified' => true
            )
        );

    });
}
  • 0
    Спасибо @ aowie1 - я уже пробовал это, но это ошибки, потому что Table::insert() не является допустимым методом

Ещё вопросы

Сообщество Overcoder
Наверх
Меню