我在 Laravel 5.1 中使用数据库迁移和播种。
迁移
public function up()
{
Schema::create('teachers', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->integer('teacher_id')->unsigned();
$table->boolean('disable')->default(0);
$table->timestamps();
$table->unique(['user_id', 'teacher_id']);
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('teacher_id')->references('id')->on('users')->onDelete('cascade');
});
}
*** user_id 和 Teacher_id 必须是唯一的。
模型工厂
$factory->define(App\Teacher::class, function ($faker) {
return [
'user_id' => $faker->numberBetween(1, 59),
'teacher_id' => $faker->numberBetween(1, 59),
];
});
我在
DatabaseSeeder.php
中设置了用于生成 500 个教师关系的播种器:
factory(App\Teacher::class, 500)->create();
但是我收到了这个错误:
[PDOException]
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '10-11' for key 'teachers_user_id_teacher_id_
unique'
如您所见,***(唯一属性)导致了错误。 有什么办法可以解决吗?你的想法是什么?
您可以获取
User
模型的集合,然后在 while
循环中从该集合中的随机 ID 中分配对:
$users = User::all(['id']);
while ($users->count() > 1) {
// Get random user for a teacher, and remove from collection
$teacher = $users->random();
$users->pull($teacher->getKey());
// Get random user and remove from collection
$user = $users->random();
$users->pull($user->getKey());
Teacher::create([
'user_id' => $user->getKey(),
'teacher_id' => $teacher->getKey(),
]);
}
如果数据库中存在唯一记录,您可以抛出异常。然后在 Seeder 类中,使用 try-catch 块,捕获异常不执行任何操作。如果遇到现有记录,则应继续播种。
示例:假设
product_stocks
表中有 3 列,其中 product_id
、color_id
和 size_id
是唯一的。
工厂类:
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
$productId = $this->faker->randomElement(Product::pluck('id')->toArray());
$colorId = $this->faker->randomElement(Color::pluck('id')->toArray());
$sizeId = $this->faker->randomElement(Size::pluck('id')->toArray());
$exists = ProductStock::where([
['product_id', '=', $productId],
['color_id', '=', $colorId],
['size_id', '=', $sizeId],
])->exists();
if ($exists) {
throw new Exception('duplicate value');
}
return [
'product_id' => $productId,
'color_id' => $colorId,
'size_id' => $sizeId,
'stok_ready' => $this->faker->numberBetween(0, 100),
];
}
播种者类别:
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
try {
ProductStock::factory()
->count(Product::count() * rand(5, 10))
->create();
} catch (Exception $e) {
// do something
}
}
使用
unique
方法尝试此解决方案:
$factory->define(App\Teacher::class, function ($faker) {
return [
'user_id' => User::all()->unique()->random()->id,
'teacher_id' => Teacher::all()->unique()->random()->id,
];
});
/**@var array $unique*/
$repeatRandom = static function () use (&$unique, &$repeatRandom) {
$userId = User::pluck('id')->random();
$teacherId = User::pluck('id')->random();
$newPair = [
$userId, $teacherId
];
foreach ($unique as $items) {
if (!array_diff_assoc($items, $newPair)) {
return $repeatRandom($unique);
}
}
return $newPair;
};
$factory->define(Teacher::class, static function (Faker $faker) use (&$unique, &$repeatRandom) {
$userId = User::pluck('id')->random();
$teacherId = User::pluck('id')->random();
$newPair = [
$userId, $teacherId
];
if (is_array($unique)) {
foreach ($unique as $items) {
if (!array_diff_assoc($items, $newPair)) {
$newPair = $repeatRandom($unique);
}
}
}
$unique[] = $newPair;
return [
'user_id' => $newPair[0],
'teacher_id' => $newPair[1]
];
}