Laravel 5.6 如何为存在关联关系的表执行数据填充
搞定Laravel关联表的数据填充(Seeder)
嘿,这个问题我之前刚处理过!关联表的Seeder确实不像单表那么直观,但Laravel的Eloquent关联机制其实已经给咱们铺好了路,咱们一步步来解决你的场景——客户、客户地址、客户购买记录这三张关联表的填充。
首先,先确保你的模型关联已经正确定义,这是一切的基础:
1. 定义模型关联
在你的Customer模型里,添加和地址、购买记录的一对多关联:
// App\Models\Customer.php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; class Customer extends Model { protected $fillable = ['name', 'email', 'phone']; // 根据你的表字段调整 public function addresses(): HasMany { return $this->hasMany(CustomerAddress::class); } public function purchases(): HasMany { return $this->hasMany(CustomerPurchase::class); } }
然后在CustomerAddress和CustomerPurchase模型里,定义反向的属于关联:
// App\Models\CustomerAddress.php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; class CustomerAddress extends Model { protected $fillable = ['customer_id', 'street', 'city', 'postcode']; // 调整字段 public function customer(): BelongsTo { return $this->belongsTo(Customer::class); } }
// App\Models\CustomerPurchase.php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; class CustomerPurchase extends Model { protected $fillable = ['customer_id', 'product_name', 'amount', 'purchase_date']; // 调整字段 public function customer(): BelongsTo { return $this->belongsTo(Customer::class); } }
2. 用Factory批量生成关联数据
Laravel的Factory是处理测试数据填充的神器,配合关联方法能快速生成带关联的批量数据。先给每个模型创建Factory:
客户模型Factory
// database/factories/CustomerFactory.php namespace Database\Factories; use App\Models\Customer; use Illuminate\Database\Eloquent\Factories\Factory; class CustomerFactory extends Factory { protected $model = Customer::class; public function definition() { return [ 'name' => $this->faker->name(), 'email' => $this->faker->unique()->safeEmail(), 'phone' => $this->faker->phoneNumber(), ]; } }
地址模型Factory
// database/factories/CustomerAddressFactory.php namespace Database\Factories; use App\Models\CustomerAddress; use Illuminate\Database\Eloquent\Factories\Factory; class CustomerAddressFactory extends Factory { protected $model = CustomerAddress::class; public function definition() { return [ 'street' => $this->faker->streetAddress(), 'city' => $this->faker->city(), 'postcode' => $this->faker->postcode(), ]; } }
购买记录模型Factory
// database/factories/CustomerPurchaseFactory.php namespace Database\Factories; use App\Models\CustomerPurchase; use Illuminate\Database\Eloquent\Factories\Factory; class CustomerPurchaseFactory extends Factory { protected $model = CustomerPurchase::class; public function definition() { return [ 'product_name' => $this->faker->word(), 'amount' => $this->faker->randomFloat(2, 10, 1000), 'purchase_date' => $this->faker->dateTimeBetween('-1 year', 'now'), ]; } }
3. 编写Seeder关联生成数据
现在创建CustomerSeeder,用Factory的has()方法一次性生成客户及其关联的地址和购买记录:
// database/seeders/CustomerSeeder.php namespace Database\Seeders; use App\Models\Customer; use Illuminate\Database\Seeder; class CustomerSeeder extends Seeder { public function run() { // 生成20个客户,每个客户随机关联1-3个地址、2-5条购买记录 Customer::factory() ->count(20) ->hasAddresses(rand(1, 3)) // 对应Customer模型里的addresses关联方法 ->hasPurchases(rand(2, 5)) // 对应purchases关联方法 ->create(); } }
如果你需要更灵活的控制(比如给不同客户设置不同的关联数量),也可以用each()方法逐个处理:
Customer::factory() ->count(10) ->create() ->each(function ($customer) { // 给这个客户生成1个默认地址 $customer->addresses()->save(CustomerAddress::factory()->make()); // 随机生成1-4条购买记录 $customer->purchases()->saveMany( CustomerPurchase::factory()->count(rand(1,4))->make() ); });
4. 运行Seeder
最后,在DatabaseSeeder里调用这个Seeder:
// database/seeders/DatabaseSeeder.php namespace Database\Seeders; use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder { public function run() { $this->call([ CustomerSeeder::class, ]); } }
然后执行命令运行填充:
php artisan db:seed
这样就能自动把关联的客户、地址、购买记录都插入到数据库里了,完全不用手动处理customer_id的关联字段,Eloquent会自动帮你填充!
内容的提问来源于stack exchange,提问作者Rlemm1991
相关产品推荐
相关产品推荐

