2016-11-11 86 views
7

在laravel的eloquent ORM中,有沒有一種方法來定義模型的允許屬性?雄辯的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是可以的,但對於任何其他情況,原則是優越的。雄辯違反了很多編程原則,他們這樣做是爲了讓它「更容易」(我們可以爭論)來協同工作。我只是給初學者提供建議,所以他們不必在編程之旅中走很長的路。 –

+2

@SteffenBrem Laravel本身違反了很多編程原則。這就是爲什麼它對於真正的項目非常方便。 )Symfony是那些喜歡以便利和更高的發行速度滿足所有已知編程原則的人的另一個偉大框架。 –

回答

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

當你把這樣的屬性,Laravel usesfill()方法,它是mass assignment功能部分:

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

所以,使其工作添加要保存到$fillable陣列中的所有允許值:

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

不幸的是,這並沒有告訴我有關無效屬性 - 因爲使用了「fillableFromArray」,所以它們被無聲地丟棄。 – cweiske

+0

@cweiske你應該手動驗證輸入數據。你不想得到SQL錯誤或者什麼,你想知道在你試圖保存數據之前某個字段是否爲空。 –

2

您可以使用laravel存在:對於每個輸入列的驗證規則。
請查看文檔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在這個意義上是故意寬容的,如果我在某處設置屬性時犯了一個錯誤,我個人並不介意有一個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的答案](http://stackoverflow.com/a/41098491/2053165)結合一點,並且只在基本模型類中寫入一次,如果你沒有不想複製粘貼到你擁有的每個模型中。這實質上是驗證你自己的代碼,所以你可以找到錯別字。 – Leith

1

如果我正確理解你,Eloquent Events可能對你有幫助。 然後,您可以將輸入數組與可填充數組進行比較。