Заполнение базы данных в файле миграции Laravel
Я только изучаю 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' => 'name@domain.com',
'verified' => true
)
);
});
}
Но я получаю следующую ошибку при запуске php artisan migrate
:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'vantage.users' doesn't exist
Это очевидно, потому что Artisan еще не создал таблицу, но вся документация говорит, что есть способ использовать Fluent Query для заполнения данных как часть миграции.
Кто-нибудь знает как? Спасибо!
10 ответов
Не помещайте 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' => 'name@domain.com',
'verified' => true
)
);
}
Я знаю, что это старый пост, но так как он появляется в поиске в 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
требуется для включения сеялки в производственной среде.
Вот очень хорошее объяснение того, почему использование Сеялки баз данных Laravel предпочтительнее, чем использование миграций: http://laravelbook.com/laravel-database-seeding/
Хотя, следуя инструкциям на официальной документации, это гораздо лучшая идея, потому что реализация, описанная по ссылке выше, кажется, не работает и является неполной. http://laravel.com/docs/migrations
Если вы используете Laravel 8 и хотите инициализировать несколько записей, вы можете сделать это любым из этих двух способов.
1. Не рекомендуемый способ
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
DB::table('categories')->insert(
array(
[
'name' => 'Category1',
],
[
'name' => 'Category2',
],
[
'name' => 'Category3',
],
)
);
}
Вышеупомянутый метод хорош, но оставит пустыми столбцы created_at и updated_at .
2. Рекомендуемый способ
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
$data = array(
[
'name' => 'Category1',
],
[
'name' => 'Category2',
],
[
'name' => 'Category3',
],
);
foreach ($data as $datum){
$category = new Category(); //The Category is the model for your migration
$category->name =$datum['name'];
$category->save();
}
}
Это должно делать то, что вы хотите.
public function up()
{
DB::table('user')->insert(array('username'=>'dude', 'password'=>'z19pers!'));
}
Я пробовал этот метод вставки в БД, но, поскольку он не использует модель, он проигнорировал вялую черту, которая была у меня на модели. Итак, учитывая, что Модель для этой таблицы существует, как только она была перенесена, я решил, что модель будет доступна для вставки данных. И я придумал это:
public function up() {
Schema::create('parent_categories', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('slug');
$table->timestamps();
});
ParentCategory::create(
[
'id' => 1,
'name' => 'Occasions',
],
);
}
Это сработало правильно, а также приняло во внимание свойство sluggable в моей модели для автоматической генерации слага для этой записи и также использует временные метки. NB. Добавление идентификатора не было обязательным, однако в этом примере мне нужны были конкретные идентификаторы для моих категорий. Протестировано на Laravel 5.8.
Еще один простой способ сделать это - определить закрытый метод, который создает экземпляр и сохраняет соответствующую модель.
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.
РЕДАКТИРОВАТЬ: лучше использовать систему сеялки, чтобы различить создание структуры базы данных и заполнение базы данных.
Отредактировав первый вариант из ответа Мартина Мбае , если вы хотите получить тот же результат, что и второй вариант, но не используя модель, вы можете просто сделать это:
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
$sampleData = ['sample1', 'sample2', 'sample3'];
$data = [];
foreach ($sampleData as $sample) {
$data[] = [
'table_name' => $sample,
'created_at' => now(),
'updated_at' => now()
];
}
DB::table('categories')->insert($data);
}
Если вы уже заполнили столбцы и добавили новые или хотите заполнить старый столбец новыми фиктивными значениями, сделайте следующее:
public function up()
{
DB::table('foydabars')->update(
array(
'status' => '0'
)
);
}
Попробуйте: (не проверено)
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' => 'name@domain.com',
'verified' => true
)
);
});
}