Eloquent ORM:定义允许的模型属性

时间:2016-11-11 12:52:19

标签: laravel eloquent

在laravel的eloquent ORM中,有没有办法定义模型的允许属性?

默认情况下,我可以将任何属性放入模型的构造函数中 - 但是当我实际尝试将模型保存到数据库时,我只会收到有关错误属性名称的通知。

示例代码:

// this works although there is a typo in "lastname"
$user = new \App\User(['firstname' => 'foo', 'lastnam' => 'bar']);

// this errors out with an SQL error
$user->save();

那么,有没有办法让Laravel自动检查请求的输入数据中是否存在无效密钥?

6 个答案:

答案 0 :(得分:5)

我不相信这可以在本地完成。我认为Laravel在这个意义上是故意宽容的,如果我在某处设置属性时出错,我个人不会介意出现SQL错误而不是Eloquent错误。

话虽如此,当设置不存在的属性时,自定义模型失败并不难:

// User.php

protected $fillable = [
    'firstname',
    'lastname',
];

public function fill(array $attributes)
{
    foreach ($attributes as $key => $value) {
        if (!in_array($key, $this->getFillable())) {
            throw new \Exception("Attribute [{$key}] is not fillable.");
        }
    }

    return parent::fill($attributes);
}

答案 1 :(得分:4)

当您添加这样的属性时,Laravel uses fill()方法属于mass assignment功能:

if ($this->isFillable($key)) {
    $this->setAttribute($key, $value);
} elseif ($totallyGuarded) {
    throw new MassAssignmentException($key);
}

因此,要使其工作,请将要保存的所有允许值添加到$fillable数组中:

$fillable = ['firstname', 'lastname'];

答案 2 :(得分:4)

您可以覆盖模型构造函数并在那里验证:

use Illuminate\Support\Facades\Schema;
//...

public function __construct(array $attributes = [])
{
    $columns = Schema::getColumnListing($this->table);

    foreach ($attributes as $attribute => $value) {
        if (! in_array($attribute, $columns)) {
            // not allowed
        }
    }

    parent::__construct($attributes);
}

答案 3 :(得分:4)

如果您不想阻止不仅使用fill()方法填充不允许的属性,而且还要直接设置它们,例如$model->foo = 'bar',那么您必须覆盖Model::setAttribute()方法。

最好在扩展Eloquent的自定义基础模型中执行此操作。所以在app/Model.php

namespace App;

use Exception;
use Illuminate\Database\Eloquent\Model as Eloquent;

class Model extends Eloquent
{
    // this should be actually defined in each sub-model
    protected $allowed = ['firstname', 'lastname'];

    public function setAttribute($key, $value)
    {
        // this way we can allow some attributes by default
        $allowed = array_merge($this->allowed, ['id']);

        if (! in_array($key, $allowed)) {
            throw new Exception("Not allowed attribute '$key'.");
        }

        return parent::setAttribute($key, $value);
    }
}

然后,在不允许无效属性的模型中,您可以扩展此基本模型:

use App\Model;

class User extends Model

答案 4 :(得分:2)

您可以使用laravel exists:每个输入的列验证规则 请查看文档https://laravel.com/docs/5.3/validation#rule-exists

OR

你可以为此目的做好帮助

$ table是表名

function validateInputColumns($table, array $inputs) 
{
    $unknownCols = null;

    $i = 0;

    foreach ($inputs as $key => $val) {
        if (! Schema::hasColumn($table, $key)) {
            $unknownCols[$i] = $key;

            $i++;
        }
    }

    return is_null($unknownCols) ? true : $unknownCols;
}

它将返回数组中的未知列列表。

答案 5 :(得分:1)

如果我理解正确,Eloquent Events可能会对您有所帮助。 然后,您可以将输入数组与可填充数组进行比较。