1

我正在使用 Ardent,并且在插入/更新相关模型时遇到了忽略 $fillable 列表的奇怪行为。我定义了以下模型:

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 字段?!

4

6 回答 6

3

我不明白为什么 HasManyOrOne 关系故意忽略可填充。这似乎真的违反直觉。无论哪种方式,我认为这应该适合你。

$user->contacts()->save(Contact::create([ ... ]));
于 2013-11-19T15:00:31.523 回答
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;
    }

    ...
}

我仍在寻找控制这种行为的充分解决方案。

于 2013-11-19T14:49:51.497 回答
0

如官方文档中所述:

要开始,请在模型上设置可填充受保护的属性。

你已经设置了两者。您应该删除以下行:protected $guarded = ['*'];

于 2013-11-19T13:20:02.543 回答
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);
    }
}
于 2014-02-27T15:42:09.567 回答
0

使用protected $guarded = array();代替protected $guarded = ['*'];

通过使用[*]你告诉 laravel 保护所有实体免受自动水合/质量分配!

array()将此$guarded列表设置为空。

可填充属性指定哪些属性应该是可批量分配的。这可以在类或实例级别设置。

可填充的逆被保护,并用作“黑名单”而不是“白名单”:

在Laravel 文档中阅读更多关于批量分配的信息

于 2014-08-29T04:40:24.247 回答
0

更新方法不在模型级别,并且不会尊重 $fillable 字段。

您可以使用 Input::only['fillable fields here'] 过滤输入数据

于 2015-07-22T22:56:11.817 回答