を私はあなたがアプローチを、以下のお勧め:
- はあなたがネストされたオブジェクトのプロパティ名と同じ関係名(いくつかのルールがあるとしましょう
$model->link()
メソッドを呼び出す必要があります)
- ネストされたモデルを持つモデルの共通クラスを宣言します(例:ActiveRecordWithNestedモデル)リフレクションを使用して(これらの操作のためのカスケードを実行するための一般的なクラスメソッド
save
とvalidate
で
- オーバーライド)
- あなたのモデルが
validate
を上書きする代替手段として、
それともこの共通のクラスを継承しますしてみましょうメソッドでは、共通クラスのrules
メソッドの適切な実装をいくつか構築できます。
次のように、この一般的なクラス缶が見えます(これは単純な案、テストされていない、ただ概念を示すためである):
class Heart extends ActiveRecordWithNestedModels
{
}
class Human extends ActiveRecordWithNestedModels
{
/* @var Heart $heart */
public $heart = null;
/**
* The relation name will be 'heart', same as property `heart'
*
* @return \yii\db\ActiveQuery
*/
public function getHeart()
{
return $this->hasOne(Heart::className(), ['id', 'heart_id']);
}
}
:次に
<?php
namespace app\models;
use yii\db\ActiveRecord;
class ActiveRecordWithNestedModels extends ActiveRecord
{
public function save($runValidation = true, $attributeNames = null)
{
$saveResult = parent::save($runValidation, $attributeNames);
$class = new \ReflectionClass($this);
foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
$propertyValue = $property->getValue($this);
if (!empty($propertyValue) && is_subclass_of($propertyValue, ActiveRecord::className())) {
/* @var ActiveRecord $nestedModel */
$nestedModel = $propertyValue;
$nestedModel->save($runValidation);
$relation = $property->name;
$this->link($relation, $nestedModel);
}
}
return $saveResult;
}
public function validate($attributeNames = null, $clearErrors = true)
{
$class = new \ReflectionClass($this);
foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
$propertyValue = $property->getValue($this);
if (!empty($propertyValue) && is_subclass_of($propertyValue, ActiveRecord::className())) {
/* @var ActiveRecord $nestedModel */
$nestedModel = $propertyValue;
if (!$nestedModel->validate(null, $clearErrors)) {
array_push($this->errors, [
$property->name => $nestedModel->errors
]);
}
}
}
parent::validate($attributeNames, $clearErrors);
if ($this->hasErrors()) return false;
return true;
}
}
あなたのモデルにすることができますが、このようになります。あなたが行うことができます
そして、(理論的に):
$human = new Human();
$human->heart = new Heart();
$human->save();
P.ここは、例えば、さらなる実装では多くの複雑な詳細については、することができ、いくつかの子オブジェクトが
オーバーライドdelete
が
場合カスケードをスキップone-to-many
とmany-to-many
関係を提供し、保存に失敗した場合save
をロールバックするトランザクションを使用して
- プロパティには対応する関係はありません
$attributeNames
をカスケード演算で実行
- など
DBテーブルのモデルの関係は、通常、すべての書き込みの試行時にも適用されるため、何を検証するかはわかりません。サポートされている場合、DBレベルでは、TRANSACTIONブロック(失敗または成功)が表示されます。あなたはYiフレームワークからメソッドを探していますか?ありがとう。 – Dilettant
ねえ、私はあなたにそれを明確にしようとします。 "true"パラメータで$ human-> save(true)を呼び出すと、モデル検証が強制されます。だから私の最初の質問です:私は1つのモデル(上記の例のような)で異なるモデルを持っている場合、 "サブモデル"も検証されていますか? 2番目の質問: モデルにモデルを入れるという目標には、どうすればアクセスできますか?これを達成するために私のメインモデルと私のサブモデルで何をしなければならないのですか? – jiGL
@jiGL yii2のModelクラスには 'save()'メソッドがありません。 ActiveRecordやその他のORM実装を使用していますか? – oakymax