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

问题描述 投票:0回答:6

在 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 自动检查请求的输入数据中是否存在无效键?

php laravel eloquent
6个回答
7
投票

如果您不仅想防止使用

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

6
投票

我不相信这可以在本地完成。我认为 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);
}

4
投票

当您添加这样的属性时,Laravel 使用

fill()
方法,该方法是质量分配功能的一部分:

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

因此,为了使其正常工作,请将要保存的所有允许值添加到

$fillable
数组中:

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

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);
}

2
投票

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

您可以为此目的制作助手

$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;
}

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


1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.