У меня есть 3 таблицы: Категории, книги и авторы: Отношения:
Я хотел бы вставить фиктивные данные, используя фабрику и сеялки. Поэтому сначала я создаю файлы миграции и модели для категорий и книг.
код в файле миграции book_table
public function up(): void
{
Schema::create('books', function (Blueprint $table) {
$table->id();
$table->foreignId('category_id')->constrained()->cascadeOnDelete();
$table->foreignId('author_id')->constrained()->cascadeOnDelete();
$table->string('book_title' , 2500);
$table->text('book_desc');
$table->string('book_image');
$table->timestamps();
});
и в файле миграции категории_таблицы
public function up(): void
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('cat_name');
$table->timestamps();
});
}
и в DatabaseSeeder
\App\Models\Category::factory(3)
->create()
->each(function ($category) {
\App\Models\Book::factory(4)
->create(['category_id' => $category->id]);
});
Итак, я могу распределять данные между категориями <> книг.
затем я создаю файлы миграции и модели для автора
файл миграцииauthor_table
public function up(): void
{
Schema::create('authors', function (Blueprint $table) {
$table->id();
$table->string('author_name');
$table->timestamps();
});
}
Но когда я попытался добавить фабрику в DatabaseSeeder для автора, вот так:
public function run(): void
{
\App\Models\Category::factory(3)
->create()
->each(function ($category) {
\App\Models\Book::factory(4)
->create(['category_id' => $category->id]);
});
\App\Models\Author::factory(5)
->create()
->each(function ($author) {
\App\Models\Book::create(['author_id' => rand(1, 5)]);
});
}
У меня 2 ошибки:
SQLSTATE[HY000]: Общая ошибка: 1005 Невозможно создать таблицу
booky.books(ошибка: 150 «Ограничение внешнего ключа сформировано неправильно») (Соединение: mysql, SQL: изменить таблицуbooksдобавить ограничениеbooks_author_id_foreignссылки на внешний ключ (author_id)authors(id) при каскадном удалении)
и
SQLSTATE[HY000]: общая ошибка: 1364 Поле «author_id» не имеет значения по умолчанию.
Я попытался вручную вставить поддельные данные в таблицу автора MySQL, но получил те же ошибки.
Любая помощь по этому вопросу будет принята с благодарностью






Хорошо, это две разные вещи, я их разберу.
Проблема, насколько я понимаю, заключается в том, что вы отредактировали исходную миграцию книг после создания таблицы авторов.
Другими словами, миграция ваших книг зависит от миграции авторов и категорий, которая выполнялась до нее.
Миграции выполняются по порядку, поэтому при запуске миграции происходит сбой в первой (книги), поскольку она пытается добавить ограничение внешнего ключа в таблицу, которая не существует (авторы).
php artisan migrate:freshdatabase/
migrations/
2024_03_16_000001_create_categories_table.php
2024_03_16_000002_create_authors_table.php
2024_03_16_000003_create_books_table.php
books.author_id (и внешний ключ) в таблицу book.return new class extends Migration
{
public function up(): void
{
Schema::table('books', function (Blueprint $table) {
$table->foreignId('author_id')
->constrained('authors')
->cascadeOnUpdate()
->cascadeOnDelete();
});
}
public function down(): void
{
Schema::table('books', function (Blueprint $table) {
$table->dropForeign(['author_id']);
$table->dropColumn('author_id');
});
}
}
Как следует из ошибки, проблема возникает из-за того, что вы вставляете строки в таблицу книг без указания идентификатора автора. Раньше это не было проблемой, потому что у вас не было столбцаauthor_id.
Обновите свои фабрики или свой код, чтобы убедиться, что ни одна книга не сохраняется с нулевым значением в столбцеauthor_id.
use App\Models\Author;
use App\Models\Book;
use App\Models\Category;
// Create 4 Authors
$authors = Author::factory()->count(4)->create();
// Create 3 Categories
$categories = Category::factory()->count(3)->create();
// Make 5 Books (make does not save to the database)
$books = Book::factory()->count(5)->make()
->each(function (Book $book) use ($authors, $categories) {
// fill relevant fields
$book->author_id = $authors->random()->id;
$book->category_id = $categories->random()->id;
// now save to the database
$book->save();
});
В качестве альтернативы вы можете просто поручить эту задачу своей книжной фабрике.
class BookFactory extends Factory
{
public function definition(): array
{
return [
'author_id' => Author::factory(),
'category_id' => Category::factory(),
'book_title' => fake()->sentence,
'book_desc' => fake()->paragraph,
'book_image' => fake()->imageUrl,
];
}
}
И тогда все, что вам нужно сделать, это вызвать Book::factory()->count(5)->create();, чтобы получить 5 книг, 5 категорий и 5 авторов.
Огромное спасибо не только за правильное решение, но и за четкое объяснение. Меня устраивает.
\App\Models\Author::factory(5)->create(); \App\Models\Category::factory(3)->create()->each(function ($category) { \App\Models\Book::factory(4)->create([ 'category_id' => $category->id, 'author_id' => \App\Models\Author::all()->random()->id // Assign a random author_id ]); });``` Это должно помочь вам