Laravel工厂填充password字段失效问题求助
我是拉丁裔,英语水平有限。我尝试使用Laravel工厂类填充MySQL数据库,Provider与Provider User之间存在多态多对多关系。
我的UserFactory.php代码:
$factory->define(User::class, function (Faker $faker) { $now = new DateTime("now", new DateTimeZone("America/Bogota")); return [ "name" => $faker->name(), "email" => $faker->unique()->safeEmail(), "password" => Hash::make("12345678"), "created_at" => $now->format("Y-m-d H:i:s"), "updated_at" => $now->format("Y-m-d H:i:s") ]; }); $factory->state(User::class, "provider-user", function(){ return ["role_id" => config("static.role_ids.provider-user")]; });
ProviderSeeder.php代码:
public function run() { factory(Provider::class, 10) ->state("natural") ->create() ->each(function($provider){ $provider->users()->createMany( factory(User::class, rand(3, 6)) ->states("provider-user") ->make() ->toArray() ); $provider->location()->save( factory(Location::class) ->make(["owner_type" => "App\Models\Provider"]) ); }); }
我已按标准方式定义了Provider.php与User.php模型间的关联,且User.php模型的password字段被加入$hidden数组中。
ProviderFactory.php和LocationFactory.php均可正常工作,但执行数据填充时出现General error: 1364 Field 'password' doesn't have a default value错误,将password字段从User.php模型的$hidden数组中移除后,一切恢复正常。
问题出在->toArray()方法上:Laravel模型的toArray()会自动排除$hidden数组里的字段,所以当你把工厂生成的User模型转成数组时,password字段被过滤掉了,createMany用这个数组插入数据库时,就缺少了必填的password字段,导致数据库报错。
你可以用以下两种方式解决:
方案1:移除->toArray()
createMany方法可以直接接受Eloquent模型实例的集合,不需要转成数组。修改ProviderSeeder.php中的代码:
$provider->users()->createMany( factory(User::class, rand(3, 6)) ->states("provider-user") ->make() );
直接传入make()生成的模型集合,Laravel会从模型实例中读取所有属性(包括$hidden里的password),不会丢失字段。
方案2:保留数组但强制包含password
如果你一定要用数组格式,可以通过以下方式强制包含password字段:
方式A:使用getAttributes()
getAttributes()会返回模型的所有原始属性(包括$hidden字段):
$provider->users()->createMany( factory(User::class, rand(3, 6)) ->states("provider-user") ->make() ->map(function($user) { return $user->getAttributes(); }) ->toArray() );
方式B:在toArray()中指定要包含的字段
调用toArray()时传入要包含的隐藏字段:
$provider->users()->createMany( factory(User::class, rand(3, 6)) ->states("provider-user") ->make() ->toArray(['password']) );
内容的提问来源于stack exchange,提问作者fahico98

