我在Yii2 Active Record中使用parent-> child(master-> detail)关系
当我想创建一个孩子时,我必须手动填写其父信息,如下所示:
关系:客户(1)---> (n)评论
class ClientController extends \yii\web\Controller
{
public function actionAddComment() {
$comment = new Comment;
if ($comment->load(Yii::$app->request->post())) {
$comment->client = $this->id; // Client id
$comment->save();
}
return $this->render('view', ['comment'=>$comment]);
}
}
我已经对它进行了优化,创建了一个Comment方法来执行此操作:
class Comment extends ActiveRecord {
public function newComment($client) {
$comment = new Comment;
$comment->client = $client; // Client id
return $comment;
}
}
我在评论模型中经历过之前保存,但仍然不确定是否有更好的方法。
是否有类似的内容:
$comment = new Comment(Yii::$app->request->post());
$client->save($comment); // Here the parent is writing his information to the child
或单行快捷方式:
$client->save(new Comment(Yii::$app->request->post());
无需在beforeSave中创建此逻辑?
答案 0 :(得分:1)
是的,我建议使用Active Record提供的内置link()
和unlink()
方法,您可以在控制器中使用它们来关联或取消两个模式,它们共享多对多或一对多的关系。
如果使用link( $name, $model, $extraColumns = [] )
所以你的代码可能如下所示:
$comment = new Comment;
if ($comment->load(Yii::$app->request->post())) {
$comment->link('client', $this);
}
查看docs了解详情。
现在关于在何处使用此代码来关联模型,它取决于您的应用程序的结构。我不确定通过触发事件做这件事是不是一个好习惯,你需要记住错误可能会发生 在抛出异常之前,您可能需要评估某些场景或逻辑。所以在我的情况下,我更喜欢将该代码用于我的控制器。
有时您需要像actionAddComment()
那样构建一个特定的操作,在某些其他情况下,例如当您的Post请求更新Parent模型并同时更新其相关的子模型时,Parent的更新操作ClientController::actionUpdate()
可能是一个很好的地方,也许这样的事情会起作用:
$params = Yii::$app->request->post();
$client->load($this->params, '');
if ($client->save() === false && !$client->hasErrors()) {
throw new ServerErrorHttpException('Failed to update the object for unknown reason.');
}
foreach ($params["comments"] as $comment) {
// We may be sure that both models exists before linking them.
// In this case I'm retrieving the child model from db so I don't
// have to validate it while i just need its id from the Post Request
$comment = Comment::findOne($comment['id']);
if (!$comment) throw new ServerErrorHttpException('Failed to update due to unknown related objects.');
// according to its documentation, link() method will throw an exception if unable to link the two models.
$comment->link('client', $client);
...