我正在经历一个滔滔不绝的奇怪问题。
我有两个雄辩的模型,一个用户模型和一个配置文件模型,它们都有单独的表并且具有一对一的关系。
我有一个表单,其中传递了这两个模型的数据。因此,属于User和Profile的数据存在于表单中。
我尝试从控制器中尽可能干净地执行插入:
$user = $this->users->createUser($request->all());
createUser
函数定义如下
public function createUser(array $data)
{
$user = new User($data);
// set some non relevant user options here...
$user->save();
$profile = new Profile($data);
$user->profile()->save($profile);
return $user;
}
但是这会产生一个sql错误,因为eloquent会将表单中的所有值分配给两个模型,因此User和Profile都获得了所有相同的属性,因此eloquent尝试插入到给定模型不存在的列中
我认为$fillable
字段用于防止此类事件发生,但我确实在两个模型中都定义了$fillable
字段:
// User
protected $fillable = ['email', 'password', ...];
// Profile
protected $fillable = ['first_name', 'last_name', ...];
我也尝试了这个:(new User)->fill($data)
但这不起作用,因为fill
方法也是从Model
构造函数调用的。
在我看来,这不是预期的行为,但话说回来,我可能误解了可填充的概念。任何见解将不胜感激。我知道这可以通过声明我想要发送给构造函数的每个键来解决,但这对我来说似乎非常混乱。另外,我正在使用laravel v5.2.29
修改
经过进一步的测试,我得出的结论是,这只发生在我运行数据库播种机的内部,我在那里使用这些功能。深入挖掘,我发现这是完全合理的,因为运行种子命令“unguards”基础Model类。所以这是预期的行为。
我的问题是,是否有任何方法可以覆盖此默认值,以便模型在运行种子命令时不会“无人看守”,这样我就可以使用我的帮助函数来填充我的测试数据库,或者我是必须在播种机类内手动正确定义每个数据记录吗?
答案 0 :(得分:3)
是的,从某些版本的Laravel 5.2中使用播种模型时,您会注意到无人看守。事实上它没有防备是非常合理的,但是如果你想要改变它,那么它是可能的,但不是那么简单。
以下是您应该采取的步骤:
在config/app.php
行Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class
中发表评论时,请在自定义ConsoleSupportServiceProvider
课程中添加添加行。
创建此类与原始ConsoleSupportServiceProvider
相同(实际上您可以扩展它),但在$providers
属性更改Illuminate\Database\SeedServiceProvider
中自定义
再次创建扩展原始SeedServiceProvider
的自定义SeedServiceProvider
,现在覆盖registerSeedCommand
以再次创建自定义SeedCommand
类
创建扩展原始SeedCommand
的自定义SeedCommand
类,现在您只需要更改:
public function fire()
{
if (! $this->confirmToProceed()) {
return;
}
$this->resolver->setDefaultConnection($this->getDatabase());
Model::unguarded(function () {
$this->getSeeder()->run();
});
}
到
public function fire()
{
if (! $this->confirmToProceed()) {
return;
}
$this->resolver->setDefaultConnection($this->getDatabase());
$this->getSeeder()->run();
}