书籍模型
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Book extends Model
{
use HasFactory;
public function reviews(){
// a book can have many reviews
return $this->hasMany(Review::class);
// i tried
//return $this->hasMany(Review::class, 'book_id');
//but it didn't solve the problem
}
}
审查模型
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Review extends Model
{
use HasFactory;
public function books(){
// a review is tied to one book
return $this->belongsTo(Book::class);
// I tried
//return $this->belongsTo(Book::class,'book_id');
//but it didn't work
}
}
Book 模型的迁移文件
public function up() : void
{
Schema::create('books', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->string('author');
$table->timestamps();
});
}
Review模型的迁移文件
public function up() : void
{
Schema::create('reviews', function (Blueprint $table) {
$table->id();
$table->text('review');
$table->unsignedTinyInteger('rating');
$table->timestamps();
//?defining the foreign key
// $table->unsignedBigInteger( 'book_id' );
// $table->foreign( 'book_id' )
->references( 'id' )->on( 'books' )->onDelete( 'cascade' );
//?a shorter syntax
$table->foreignId('book_id')->constrained()->cascadeOnDelete();
});
}
BookFactory 文件
public function definition() : array
{
return [
'title' => fake()->sentence(3),
'author' => fake()->name,
'created_at' => fake()->dateTimeBetween('-2 years'),
'updated_at' => fake()->dateTimeBetween('created_at', 'now')
];
}
评论工厂
class ReviewFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition() : array
{
return [
'book_id' => null,
'review' => fake()->paragraph,
'rating' => fake()->numberBetween(1, 5),
'created_at' => fake()->dateTimeBetween('-2 years'),
'updated_at' => fake()->dateTimeBetween('created_at', 'now')
];
}
//? Create state methods to create more diversity in the generated data
public function good(){
return $this->state(function (array $attributes) {
return [
'rating' => fake() -> numberBetween(4,5)
];
});
}
public function average(){
return $this->state(function (array $attributes) {
return [
'rating' => fake() -> numberBetween(2,5)
];
});
}
public function bad(){
return $this->state(function (array $attributes) {
return [
'rating' => fake() -> numberBetween(1,3)
];
});
}
}
DatabaseSeeder.php 文件
public function run() : void
{
Book::factory(34)->create()->each(function ($book) {
$numReviews = random_int(5, 30);
Review::factory()
->count($numReviews) //the number of the reviews generated
->good() // using the state method to define the 'rating'
->for($book) // associating the records to the current generated book
->create();
});
Book::factory(33)->create()->each(function ($book) {
$numReviews = random_int(5, 30);
Review::factory()
->count($numReviews)
->average()
->for($book)
->create();
});
Book::factory(33)->create()->each(function ($book) {
$numReviews = random_int(5, 30);
Review::factory()
->count($numReviews)
->bad()
->for($book)
->create();
});
}
运行“php artisan migrate:refresh --seed”时收到的错误消息
INFO Rolling back migrations.
2023_08_17_222856_create_reviews_table ...................................... 18ms DONE
2023_08_17_222848_create_books_table ......................................... 7ms DONE
2019_12_14_000001_create_personal_access_tokens_table ........................ 8ms DONE
2019_08_19_000000_create_failed_jobs_table ................................... 7ms DONE
2014_10_12_100000_create_password_reset_tokens_table ......................... 7ms DONE
2014_10_12_000000_create_users_table ......................................... 7ms DONE
INFO Running migrations.
2014_10_12_000000_create_users_table ........................................ 33ms DONE
2014_10_12_100000_create_password_reset_tokens_table ........................ 36ms DONE
2019_08_19_000000_create_failed_jobs_table .................................. 24ms DONE
2019_12_14_000001_create_personal_access_tokens_table ....................... 34ms DONE
2023_08_17_222848_create_books_table ......................................... 9ms DONE
2023_08_17_222856_create_reviews_table ...................................... 45ms DONE
INFO Seeding database.
Illuminate\Database\QueryException
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'book_id' cannot be null (Connection: mysql, SQL: insert into `reviews` (`book_id`, `review`, `rating`, `created_at`, `updated_at`) values (?, Officiis consequatur temporibus maxime sequi laudantium et. Nam non voluptas est ea. Id fugit et amet deserunt ullam laborum eveniet. Harum eos ratione voluptate debitis qui sequi., 5, 2022-11-02 05:18:02, 2022-12-06 12:41:24))
at vendor\laravel\framework\src\Illuminate\Database\Connection.php:795
791▕ // If an exception occurs when attempting to run a query, we'll format the error
792▕ // message to include the bindings with SQL, which will make this exception a
793▕ // lot more helpful to the developer instead of just the database's errors.
794▕ catch (Exception $e) {
➜ 795▕ throw new QueryException(
796▕ $this->getName(), $query, $this->prepareBindings($bindings), $e
797▕ );
798▕ }
799▕ }
1 vendor\laravel\framework\src\Illuminate\Database\Connection.php:580
PDOException::("SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'book_id' cannot be null")
2 vendor\laravel\framework\src\Illuminate\Database\Connection.php:580
PDOStatement::execute()
我原本希望找到 100 本书,每本书有 5 到 30 条评论,但当我检查 phpMyAdmin 时,我发现只有 34 本书被种子化,而且根本没有评论被种子化,但我发现外键列已添加到评论表中。
好吧,这里有很多东西要解压。
在您的审查模型中,所属函数的名称应该是单数。所以它是
book()
不是 books()
。
您忘记注释掉审核迁移文件中的
->references( 'id' )->on( 'books' )->onDelete( 'cascade' );
行。
在您的 Book- 和 ReviewFactory 中,您有
faker()->name
和 faker()->paragraph
,它们应该是函数,所以 faker()->name()
和 faker()->paragraph()
在您的 Book- 和 ReviewFactory 中,您有
fake()->dateTimeBetween('-2 years')
。我不是 100% 舒尔,但我认为它应该采用 0 或 2 个参数,例如 fake()->dateTimeBetween('-2 years', 'now')
...这就是您的错误消息的来源。在您的 ReviewFactory 中您有
'book_id' => null
。只需删除这一行即可。
在 DatabaseSeeder 中,您的代码可能如下所示:
public function run(): void
{
$book = Book::factory(34)
->has(Review::factory()->count(random_int(5, 30)), 'reviews')
->create();
}