2016-11-11 14 views
7

ORMでは、モデルの許容属性を定義する方法はありますか?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は自動的にチェックしてみましょうする方法はありますか?

+2

@SteffenBremを、私は非常にあなたがLaravelプロジェクトで雄弁代わりの教義を使用することをお勧めします。 ) –

+0

@AlexeyMezenin Eloquentはデモやプロトタイプで大丈夫ですが、他のケースではDoctrineが優れています。 Eloquentは多くのプログラミング原則に違反しています。彼らはそれを「より簡単に」(それについて論じることができます)ようにしています。私はちょうど初心者のためのアドバイスをしているので、彼らはプログラミングの旅で長い道のりを取る必要はありません。 –

+2

@SteffenBrem Laravel自体は多くのプログラミング原則に違反しています。だからこそ、実際のプロジェクトではとても便利です。 )symfonyは、すべての既知のプログラミング原則を納得させ、より高い委譲速度を尊重することを望む人々のためのもう一つの素晴らしいフレームワークです。 –

答えて

4

fill()メソッドを使用して許容されない属性を埋めるだけでなく、$model->foo = 'bar'のようにそれらを直接設定しないようにするには、Model::setAttribute()メソッドをオーバーライドする必要があります。

Eloquentを拡張したカスタムベースのモデルで最適です。その後

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

あなたは、この基本モデルを拡張することができ、無効な属性許すべきではないモデルで::だからapp/Model.php

use App\Model; 

class User extends Model 
4

あなたはLaravel usesmass assignment機能の一部ですfill()方法このような属性を追加している:それはあなたが必要なすべての許可された値が$fillable配列に保存する追加動作させるために、そう

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

を:

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

残念ながら、これは無効な属性については教えてくれません。 'fillableFromArray'が使用されているので、静かに破棄されます。 – cweiske

+0

@cweiske入力データを手動で検証する必要があります。あなたは、SQLエラーや何かをしたくない場合は、データを永続化しようとする前に、いくつかのフィールドが空であるかどうかを知りたいと思っています。 –

2

入力ごとにlaravel exists:column validationルールを使用できます。
ドキュメントにhttps://laravel.com/docs/5.3/validation#rule-exists

OR

を確認してくださいあなたは、この目的の

$表のヘルパーを作ることができ、それが配列に未知の列リストが返されますテーブル名

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

これはネイティブで行うことはできません。私はLaravelがその意味で意図的に許されていると思います。私は、属性をどこかに設定するのを間違えてしまえば、私は個人的にEloquentのSQLエラーではなくても構いません。

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

あなたはモデルコンストラクタをオーバーライドして、そこに検証することもできます:言われて、それは非既存の属性が設定されているときに失敗し、あなたのモデルをカスタマイズすることは難しいことではないということ

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

これはたぶん最善のアプローチですが、[Paul's answer](http://stackoverflow.com/a/41098491/2053165)と少し組み合わせて、ベースモデルクラスで1回だけ書くこともできますあなたが持っているすべてのモデルにこれをコピーして貼り付ける必要はありません。これは基本的にあなた自身のコードを検証しているので、タイプミスを見つけることができます。 – Leith

1

の場合私はあなたを正しく理解しており、Eloquent Eventsがあなたに役立つかもしれません。 次に、入力配列と入力可能配列を比較できます。

関連する問題