0

I am using Laravel 8 and trying to make database factories/seeders I am having some issues.

I have the following database Schema:

Schema::create('authors', function (Blueprint $table) {
    $table->id();
    $table->string('first_name');
    $table->string('last_name');
    $table->timestamps();
});

Schema::create('books', function (Blueprint $table) {
    $table->char('isbn', 13)->unique('isbn');
    $table->string('title');
    $table->string('edition');
    $table->date('release_date');
    $table->string('image');
    $table->timestamps();
});

//Create pivot table for author since its many to many relationship.
Schema::create('author_book', function (Blueprint $table) {
    $table->id();
    $table->unsignedBigInteger('author_id');
    $table->char('book_id', 13);
    $table->foreign('author_id')->references('id')->on('authors')->onDelete('cascade');
    $table->foreign('book_id')->references('isbn')->on('books')->onDelete('cascade');
});

Now I am trying to create factories and database seeders but I get an error using the following line to seed:

Book::factory()
    ->has(Author::factory()->count(2))
    ->create();

This gives me the following error:

Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails
(`bokel`.`author_book`, CONSTRAINT `author_book_book_id_foreign` FOREIGN KEY (`book_id`) REFERENCES `books` (`isbn`) ON DELETE CASCADE)
(SQL: insert into `author_book` (`author_id`, `book_id`) values (1, 0), (2, 0))

Which is if I understand it correctly because an isbn number is excpected but laravel just puts an integer into the pivot table. What would be the best way to solve this? I was thinking something like this but that doesn't work either.

Book::factory()
    ->has(Author::factory()->count(2), function (array $attributes, Book $book) {
        return ['book_id' => $book->isbn];
    })
    ->create();

The Factory definitions are the following:

public function definition()
{
    return [
        'isbn' => $this->faker->unique()->isbn13,
        'title' => $this->faker->sentence,
        'edition' => $this->faker->numberBetween(1, 10),
        'release_date' => $this->faker->date(),
        'image' => $this->faker->imageUrl(),
    ];
}

public function definition()
{
    return [
        'first_name' => $this->faker->firstName,
        'last_name' => $this->faker->lastName
    ];
}
user3658609
  • 539
  • 2
  • 6
  • 14
  • Does this help? https://stackoverflow.com/questions/38446863/laravel-5-2-migration-cannot-add-foreign-key-of-char-data-type – Tom Dec 06 '20 at 22:22
  • Unfortunately no.. The migration works without issues. Its the factory/seeder which have the issue. – user3658609 Dec 06 '20 at 22:31
  • Showing your factory definitions would be helpful here, since that's where the problem lies. – miken32 Dec 06 '20 at 22:54
  • I have added the factory definitions. – user3658609 Dec 06 '20 at 23:34
  • Can you provide a relation in your `Book` model for `Author`? I guess there is your problem . – mare96 Dec 06 '20 at 23:52
  • I already did that.. – user3658609 Dec 06 '20 at 23:53
  • I'm unable to recreate this problem, with a very similar setup on my code. You should be able to do a simple `Book::factory()->hasAuthors(2)->create();` You have specified the unconventional primary key in relationship and model definitions? – miken32 Dec 06 '20 at 23:56
  • @user3658609 No, you posted migrations. To enable factories like that you need correct relation in your models. – mare96 Dec 06 '20 at 23:59

1 Answers1

1

As I mentioned in the comment I think your problem is relation in your Book model.

In your Book model you need:

public function authors()
{
    return $this->belongsToMany(Author::class,
        'author_book', 'book_id', 'author_id', 'isbn', 'id')
        ->using(AuthorBook::class);
}

Try like that and if this doesn't solve your problem I'll delete the answer.

Take a look in the docs, and check link has many relationships in Many to Many section.

Good luck!

mare96
  • 3,749
  • 1
  • 16
  • 28