我有一个模型Foo,它对应一个包含以下列的表。
ID
说明
USER_ID
我单独设置Foo模型的属性(无质量分配)
$foo = new Foo;
$foo->id = 1;
$foo->description = "hello kitty";
$foo->user_id = 55;
//...
将$ foo发送到另一个类进行额外处理,但由于该类需要更多信息,我只想将其添加到$ foo模型中。
//...
$foo->bar = $additional_information;
Event::fire(DoStuffWithFoo($foo));
$foo->save(); //error
问题出在我$foo->save()
时,它抱怨bar
不是一列。
我知道在保存之前我可以unset($foo->bar);
,但是......
是否可以告诉Eloquent简单地忽略任何不相关的属性?
答案 0 :(得分:2)
我知道为时已晚,但您可以通过覆盖模型中的saving
函数来注册boot
操作:
protected static function boot() {
parent::boot();
static::saving(function($model) {
$savable = [...];
if (count($savable) > 0) {
$model->attributes = array_intersect_key($model->attributes, array_flip($savable));
}
});
}
这是未经测试的代码,但我们的想法是在保存模型之前删除与变量savable
不相交的属性。变量savable
是一个可保存属性的数组。例如,$savable = ['foo', 'bar']
将仅保存foo
和bar
属性。
优点:您可以批量指定您想要的任何属性而不会对fillable
或guarded
造成伤害。
缺点:未标记为savable
的属性将在保存后从模型中删除。
答案 1 :(得分:1)
只需将$bar
添加为foo类中的属性即可:
class Foo extends Model
{
public $bar;
//...
现在您可以使用save()
,Laravel不会尝试在数据库中存储bar
。
说明:
如果在模型上调用save()
,则仅将数组$model->attributes
中的那些属性保存到数据库中。如果您将$bar
定义为类Foo
中的一个属性,那么$foo->bar ="xyz"
将永远不会以数组$model->attributes
结尾。
但是,如果尚未为Foo
声明这样的属性,则会调用__set()
是因为您try to save something in an inaccessible property。
您可以签出Laravel\Illuminate\Database\Eloquent\Model.php
:
/**
* Dynamically set attributes on the model.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function __set($key, $value)
{
$this->setAttribute($key, $value);
}
基本上可以调用
$this->attributes[$key] = $value;
来自Laravel\Illuminate\Database\Eloquent\Concerns\HasAttributes.php
。
现在$foo->bar ="xyz"
会在$foo->attribute['bar']
中变成蜜蜂,这就是save()
与..this column does not exists..
崩溃的原因。
答案 2 :(得分:0)
添加$ fillable,模型将忽略不在其中的所有内容(而不是给出错误)。使用构造函数来填充所有列是可选的。
class Foo extends Model
{
protected $fillable = ['id', 'description', 'user_id'];
}
$f = new Foo(['id' => 1, 'description' => "hello monkey", 'user_id' => 55, 'bar' => 'wow']); // should work w/o error, but it ignores the 'bar'.
答案 3 :(得分:0)
我知道这个问题很旧,但是它是最近一次搜索的最高结果,其中我试图解决一个类似的问题,我认为这可能是Laravel访问器/更改器的理想案例。我已经在Laravel 5.6上进行了测试,但相信它可以早在4.2上运行。
通过创建变量和访问器而不是公共属性,它将允许将字段添加到可填充以进行批量分配,同时仍将其从内部属性中排除(从而防止了将其错误保存到数据库)。我了解原始请求已排除了大规模分配,但这并不一定排除了此答案。我认为一个示例会有所帮助:
class Foo extends Model
{
//Allow bar in mass assignment
protected $fillable = [
"bar"
];
/**
* Store bar in protected variable instead of attributes
* Because bar is not set in attributes, Laravel will not try to save it to database
*/
protected $bar;
/**
* Mutator method to set bar's value
*/
public function setBarAttribute($value)
{
$this->bar = $value;
}
/**
* Accessor method to retrieve bar's value
*/
public function getBarAttribute()
{
return $this->bar;
}
}
使用质量分配创建此模型时,如果质量分配值中存在bar,则将为bar调用mutator(setBarAttribute)方法。每当访问bar属性时,都会调用相应的get / set方法。由于增变器未在模型的内部属性变量中设置bar的值,因此模型不会将bar保存到数据库中。