2016-09-04 5 views
4

これは些細な疑問のように思えるかもしれませんが、私が考えることができる明らかな解決策のすべてには独自の欠陥があります。Yii2:ActiveRecordでデフォルトの属性値を設定する方法は?

私たちが望むのは、検証前と検証中に読み取り可能にし、検索に使用される派生クラスを妨げないように、新しいレコードに対してのみデフォルトのActiveRecord属性値を設定できることです。

デフォルト値は、(new MyModel)->attrがデフォルトのattrの値を返すように、クラスをインスタンス化するとすぐに設定して準備する必要があります。

  • A)MyModelオーバーライドinit()方法ではとisNewRecordがそうのような真の場合、デフォルト値を割り当てます:ここで

    は可能性と、彼らが持っている問題のいくつかはある

    public function init() { 
        if ($this->isNewRecord) { 
         $this->attr = 'defaultValue'; 
        } 
        parent::init(); 
    } 
    

    問題:検索。 MySearchModelの既定の属性を明示的に設定しない限り(忘れやすいのでエラーが発生しやすい)、派生したMySearchModelクラスのsearch()を呼び出して検索を妨げる前に値を設定します(attr属性は既に設定されています)。検索で間違った結果が返されます)。 Yii1.1では、search()を呼び出す前にunsetAttributes()を呼び出して解決しましたが、Yii2ではそのようなメソッドは存在しません。 MyModelオーバーライドbeforeSave()方法において

  • B)ようなので:

    public function beforeSave($insert) { 
        if ($insert) { 
         $this->attr = 'defaultValue'; 
        } 
        return parent::beforeSave(); 
    } 
    

    問題:項目は保存されていないレコードに設定されていません。 (new MyModel)->attrnullです。さらに悪いことに、この値に依存する他の検証規則でさえ、が検証後にと呼ばれているため、この値にアクセスすることはできません。

  • C)値は、我々が代わりにbeforeValidate()メソッドをオーバーライドして、そのようにそこデフォルト値を設定することができ、検証時に利用可能であることを確認するには、次の

    public function beforeValidate() { 
        if ($this->isNewRecord) { 
         $this->attr = 'defaultValue'; 
        } 
        return parent::beforeValidate(); 
    } 
    

    問題:属性はまだで設定されていません保存されていない(未検証の)レコード。デフォルト値を取得する場合は、少なくとも$model->validate()に電話する必要があります。 Bと同じ)およびC):

    public function rules() { 
        return [ 
         [ 
          'attr', 'default', 
          'value' => 'defaultValue', 
          'on' => 'insert', // instantiate model with this scenario 
         ], 
         // ... 
        ]; 
    } 
    

    問題:そう等検証中に、デフォルトの属性値を設定する

  • D)rules()使用DefaultValidator。実際にレコードを保存または検証するまで、値は設定されません。

だから何は、デフォルトの属性値を設定するための正しい方法ですか?説明されている問題がなければ他の方法はありますか?

+0

$ model = new DatabaseTable(); $ modelはデータベーステーブルのすべてのデフォルト属性を持っています。 – Coz

+0

@Coz Nopeは、現在のユーザIDなどの動的な属性に対しては機能しません。 – mae

+0

それは、ちょうどカスタムコールバックを使用します。しかし、現在のユーザーIDを使用する場合は、代わりにhttp://www.yiiframework.com/doc-2.0/yii-behaviors-blameablebehavior.htmlを使用してください。 – Coz

答えて

2

私はそれが答えられていることを知っていますが、私は私のアプローチを追加します。 私はApplicationとApplicationSearchモデルを持っています。アプリケーションモデルでは、現在のインスタンスのチェックでinitを追加します。そのApplicationSearch私は初期化をスキップします。コードになるので、あなたは非検索ベースモデルに名前を検索して任意のメソッドを追加しなかったと仮定すると、現在のインスタンス内の検索方法が存在するかどうかを確認することができます下のコメント@maeとしても

public function init() 
    { 
     if(!$this instanceof ApplicationSearch) 
     { 
      $this->id = hash('sha256', 123); 
     } 

     parent::init(); 
    } 

、:

public function init() 
    { 
     // no search method is available in Gii generated Non search class 
     if(!method_exists($this,'search')) 
     { 
      $this->id = hash('sha256', 123); 
     } 

     parent::init(); 
    } 
+1

私はこの最高のことが好きで、それは私にさらに良いアイデアを与えました。代わりに '!method_exists($ this、 'search')'をチェックして、子クラス名を知る必要はありません。 – mae

0

私はあなたの質問を何度も読んできましたが、いくつかの矛盾があると思います。
検証前と検証中に既定値を読み取り、次にinit()またはbeforeSave()を試してみます。したがって、モデルのデフォルト値をライフサイクルの中で可能な限り長くし、派生したクラスに干渉しないようにするには、単にオブジェクトを初期化した後でそれらを設定するだけです。

すべてのデフォルトが設定されている別の方法を準備し、明示的に呼び出すことができます。

​​

または、すべてのデフォルト値が設定されたモデルを作成し、そのインスタンスを返す静的メソッドを作成できます。

$model = Model::createNew(); 

または、コンストラクタにデフォルト値を渡すことができます。

$model = new Model([ 
    'attribute1' => 'value1', 
    'attribute2' => 'value2', 
]); 

これは、属性を直接設定することとあまり変わりません。

$model = new Model; 
$model->attribute1 = 'value1'; 
$model->attribute2 = 'value2'; 

あなたのモデルがあなたのコントローラーにどれくらい透明であるかによって、すべてのことが決まります。

このように、属性は直接初期化を除くライフサイクル全体にわたって設定され、派生検索モデルと干渉しません。

+1

'new'キーワードの代わりに' Yii :: createObject'を使うのは良いことです。 – meysam

+0

なぜですか? 'new'はずっと高速です。 – Bizley

+0

'Yii :: createObject'は新しいもの以上のことを可能にします。私の意見では、Yii2のセマンティックスキーマも保存されています。すべての初期化は1か所にあり、異なる場所でも異なる方法でもないので、他のユーザーはコードをより理解することができます。 – meysam

8

これを行うには2通りの方法があります。

$model => new Model(); 

$modelには、データベーステーブルのすべてのデフォルト属性があります。

使用できる

またはあなたの規則で:今すぐ

[['field_name'], 'default', 'value'=> $defaultValue], 

$modelは常に、あなたが指定したデフォルト値を使用して作成されます。

あなたは、すべてのデフォルトが設定されている別の方法を用意し、それを明示的に呼び出すことができ、ここでhttp://www.yiiframework.com/doc-2.0/guide-tutorial-core-validators.html

+0

オプション** D **で指摘したように、 '$ model-> validate()'が実行されるまで値が実際には設定されないので、この解決策は不十分です。 – mae

-1

をコアバリデータの完全なリストを見ることができます。

$model = new Model; 
if($model->isNewRecord()) 
    $model->setDefaultValues(); 
関連する問題