在 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 自动检查请求的输入数据中是否存在无效键?
如果您不仅想防止使用
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
我不相信这可以在本地完成。我认为 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);
}
您可以重写模型构造函数并在那里进行验证:
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);
}
您可以使用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;
}
它将返回数组中未知的列列表。
如果我理解正确的话,Eloquent Events可能对你有帮助。 然后,您可以将输入数组与可填充数组进行比较。