LARAVEL 如何从特征更改模型中的 $fillable?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35622923/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
LARAVEL how to change $fillable in Model from trait?
提问by fico7489
I have in model:
我有模型:
use seoTrait;
protected $fillable = [
'name', 'title', 'description'
];
I created trait "seoTrait" which need "seoMeta" in $fillable.
我在 $fillable 中创建了需要“seoMeta”的特征“seoTrait”。
Now I add :
现在我补充说:
protected $fillable = [
'name', 'title', 'description', 'seoMeta'
];
But is it possible in trait "seoTrait" add something to $fillable ?
但是有可能在特征“seoTrait”中向 $fillable 添加一些东西吗?
采纳答案by PeterPan666
You should be able to use the boot method of Traits like so
您应该可以像这样使用 Traits 的引导方法
public static function bootSeoTrait()
{
$this->fillable[] = 'seoMeta';
}
public static function bootSeoTrait()
{
$this->fillable[] = 'seoMeta';
}
This way whenever your model boots up, this method of your Trait will be called ans 'seoMeta'
should be added to $fillable
这样每当您的模型启动时,您的 Trait 方法都会被称为 ans'seoMeta'
应该添加到$fillable
EDIT
编辑
This answer will not work since bootSeoTrait
is a static method, $this
will not be available.
这个答案将不起作用,因为它bootSeoTrait
是一个静态方法,$this
将不可用。
See @DokiCRO answer here
请参阅此处的@DokiCRO 答案
Since this answer is accepted, I can't delete it.
由于此答案已被接受,因此我无法将其删除。
EDIT 2
编辑 2
Laravel now supports the initialize*
method to initialize model traits. See @OneBigOwnage answer here
Laravel 现在支持initialize*
初始化模型特征的方法。请参阅此处的@OneBigOwnage 答案
回答by OneBigOwnage
For anyone that came here looking for an answer; I believe that there is a better way than constructor overloading.
对于来到这里寻找答案的任何人;我相信有比构造函数重载更好的方法。
Others have pointed out that Laravel supports bootable model traits, using the boot<TraitName>
method you can set up the trait for usage. However, the boot<TraitName>
method has to be static, so you cannot alter any non-static properties of the model.
其他人指出 Laravel 支持可引导模型特征,使用该boot<TraitName>
方法可以设置特征以供使用。但是,该boot<TraitName>
方法必须是静态的,因此您不能更改模型的任何非静态属性。
However, I found out that there is a non-static equivalent to the boot<TraitName>
method; the initialize<TraitName>
method.
但是,我发现有一个非静态的等价于该boot<TraitName>
方法;的initialize<TraitName>
方法。
Internally, when Eloquent boots up a model, it also registers all initialize methods for the model, based on the methods found in the traits that the model uses. Then upon instantiating that model, the initialize methods are fired.
在内部,当 Eloquent 启动模型时,它还会根据模型使用的特征中找到的方法注册模型的所有初始化方法。然后在实例化该模型时,初始化方法被触发。
An example of usage, based on the problem stated in this question:
使用示例,基于此问题中所述的问题:
trait SEOTrait
{
/**
* This method is called upon instantiation of the Eloquent Model.
* It adds the "seoMeta" field to the "$fillable" array of the model.
*
* @return void
*/
public function initializeSEOTrait()
{
$this->fillable[] = 'seoMeta';
}
}
Sadly there isn't any information in the official documentation about either bootable or initializable traits. However, I still find it really cool that both functionalities exist.
遗憾的是,官方文档中没有关于可引导或可初始化特征的任何信息。但是,我仍然觉得这两种功能都存在真的很酷。
回答by BrynJ
I had the same requirement. However, I didn't want to declare a constructor in my trait, as this leads to very unexpected behaviour - what if another trait also declares a constructor?
我有同样的要求。但是,我不想在我的 trait 中声明一个构造函数,因为这会导致非常意外的行为 - 如果另一个 trait 也声明了一个构造函数怎么办?
As pointed out by PeterPan666, we can't use the static trait boot()
method to directly set the non-static fillable
property - but we can utilise Laravel Model Events, which receive an instance of the model.
正如 PeterPan666 所指出的,我们不能使用静态 traitboot()
方法直接设置非静态fillable
属性 - 但我们可以使用Laravel 模型事件,它接收模型的实例。
For example:
例如:
public static function bootSeoTrait() : void
{
static::retrieved(function($model) {
$model->fillable = array_merge($model->fillable, ['seoMeta']);
});
}
Update
更新
Although the $fillable
property is protected, the GuardsAttributes
trait - which the Illuminate\Database\Eloquent\Model
uses - contains the following setter:
尽管该$fillable
属性是受保护的,GuardsAttributes
但Illuminate\Database\Eloquent\Model
使用的trait包含以下 setter:
/**
* Set the fillable attributes for the model.
*
* @param array $fillable
* @return $this
*/
public function fillable(array $fillable)
{
$this->fillable = $fillable;
return $this;
}
So, we can set the $fillable
protected property from our model instance in the retrieved
event.
因此,我们可以$fillable
在retrieved
事件中从我们的模型实例设置受保护的属性。
回答by Ben V.
As @DokiCRO said, you could implement a constructor within your trait. You must then consider that there won't be any other trait that will be able to overwrite the construct.
正如@DokiCRO 所说,您可以在您的特征中实现一个构造函数。然后,您必须考虑不会有任何其他特征能够覆盖该构造。
For anything else, I would suggest to go with the static bootTraitClassName(). But in this specific case we need to overwrite a non-static protected property, which can't be achievable within a static context.
对于其他任何事情,我建议使用静态 bootTraitClassName()。但是在这种特定情况下,我们需要覆盖一个非静态受保护的属性,这在静态上下文中是无法实现的。
So this justifies the constructor overload. Maybe use one trait that is responsible for overloading $fillable arrays for all your models, which will make your life easier in the long run.
所以这证明构造函数重载是合理的。也许使用一种 trait 负责为你的所有模型重载 $fillable 数组,从长远来看这会让你的生活更轻松。
Just make sure to include your code before the parent construct gets called though.
只需确保在调用父构造之前包含您的代码。
public function __construct(array $attributes = []) {
$this->fillable[] = 'seoMeta';
parent::__construct($attributes);
}
回答by DokiCRO
You can use constructor inside your trait, but it is important to send fillable attributes to parent constructor Illuminate\Database\Eloquent\Modal
您可以在特征中使用构造函数,但将可填充属性发送到父构造函数 Illuminate\Database\Eloquent\Modal 很重要
parent::__construct($attributes);
Here is example code:
这是示例代码:
public function __construct(array $attributes = []) {
parent::__construct($attributes);
$this->fillable[] = 'seoMeta';
}