我正在使用Ardent,我在插入/更新相关模型时遇到了忽略$ fillable list的奇怪行为。 我定义了以下模型:
class User extends LaravelBook\Ardent\Ardent
{
protected $table = 'users';
public static $relationsData = [
'contacts' => [self::HAS_MANY, 'Contact'],
];
}
class Contact extends LaravelBook\Ardent\Ardent
{
protected $table = 'user_contacts';
protected $guarded = ['*'];
protected $fillable = [
'user_id',
'type',
'value'
];
public static $relationsData = [
'user' => [self::BELONGS_TO, 'User'],
];
}
现在我正在尝试向用户添加新联系人:
$user->contacts()->create([
'type' => 'some type',
'value' => 'some value',
'unknown_field' => 'unknown value'
]);
...我得到了SQL插入错误:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'unknown_field' in 'field list' (SQL: insert into `user_contacts` (`type`, `value`, `unknown_field`, `user_id`, `updated_at`, `created_at`) values (?, ?, ?, ?, ?, ?)) (Bindings: array ( 0 => 'some type', 1 => 'some value', 2 => 'unknown value', 3 => 2, 4 => '1384854899', 5 => '1384854899', ))
同时这很好用:
UserContact::create([
'user_id' => 2,
'type' => 'some type',
'value' => 'some value',
'unknown_field' => 'unknown value'
]);
我没有得到任何SQL错误,'unknown_field'被忽略了。
在通过构建器工作时,可以忽略$ fillable字段的任何想法?!
答案 0 :(得分:3)
我不明白为什么HasManyOrOne关系故意忽略可填写。这看起来非常直观。无论哪种方式,我认为这应该适合你。
$user->contacts()->save(Contact::create([ ... ]));
答案 1 :(得分:1)
我似乎找到了这种行为的原因。这在HasOneOrMany抽象类中明确实现。
abstract class HasOneOrMany extends Relation {
...
/**
* Create a new instance of the related model.
*
* @param array $attributes
* @return \Illuminate\Database\Eloquent\Model
*/
public function create(array $attributes)
{
$foreign = array(
$this->getPlainForeignKey() => $this->parent->getKey()
);
// Here we will set the raw attributes to avoid hitting the "fill" method so
// that we do not have to worry about a mass accessor rules blocking sets
// on the models. Otherwise, some of these attributes will not get set.
$instance = $this->related->newInstance();
$instance->setRawAttributes(array_merge($attributes, $foreign));
$instance->save();
return $instance;
}
...
}
我仍然在寻找足够的解决方案来控制这种行为。
答案 2 :(得分:0)
正如官方文件中所述:
要开始使用,请在模型上设置可填写的 或 防护属性。
你已经设置了两个。您应该删除以下行:protected $guarded = ['*'];
答案 3 :(得分:0)
幸运的是,这将在版本4.2中修复:https://github.com/laravel/framework/pull/2846
除此之外,您还可以手动过滤属性:
$input = [
'user_id' => 2,
'type' => 'some type',
'value' => 'some value',
'unknown_field' => 'unknown value'
];
$fillable = $user->contacts()->getRelated()->fillableFromArray($input);
$user->contacts()->create($fillable);
请记住,该示例正在使用受保护的Eloquent\Model\fillableFromArray()
方法,因此有必要对其进行复制:
class BaseModel extends Eloquent
{
public function fillableFromArray(array $attributes)
{
return parent::fillableFromArray($attributes);
}
}
答案 4 :(得分:0)
使用protected $guarded = array();
代替protected $guarded = ['*'];
使用[*]
你告诉laravel防止所有实体进行自动水合/质量分配!
array()
将此$guarded
列表设置为null。
了解详情fillable属性指定哪些属性应该是可批量分配的。这可以在类或实例级别设置。
可填写的反面被保护,并作为“黑名单”而不是“白名单”:
答案 5 :(得分:0)
更新方法不在模型级别,并且不会尊重$ fillable字段。
您可以使用Input :: only ['此处可填写字段']
来过滤输入数据