2017-08-07 18:01:25 2440次浏览 3条回答 1 悬赏 20 金钱

1.png
因为目前数据表设计是一个post帖子主表(标题、浏览量、阅读量等等字段),一个extra表(帖子ID、内容等字段),一个attach附件表(帖子ID、附件地址等字段)

要求发帖时候,同时向这几张表写入内容;编辑时同时渲染这几张表的内容。

最初我是建立了一张新的表单模型表,继承model,把需要的字段全部public形式放在这个表单模型中,通过事务进行多张表数据的写入,OK似乎没有问题,但是在编辑时,不知道怎么去渲染数据了,因为它继承了Model。无奈求助后发现有多模型同时输入章节这个章节。

原理似乎很简单,渲染多个AR模型,进行实例化,并各自load数据,然后验证,然后save保存。似乎问题可以得到解决,但是有以下几个疑问:

1、怎么去保证它的事务呢?每次都需要通过 && 进行吗?如果有更多的复合表单模型,岂不是全部都要load && 一遍? 然后全部validate &&一遍?再全部 save &&一遍? 感觉好别扭!
2、不知道我最初的办法,新建表单模型的那种是否可行? 可行的话,如何在编辑时候渲染数据呢?

最佳答案

  • drodata 发布于 2017-08-07 19:13 举报

    “新建表单模型”的思路没问题。假设:

    • 表单模型为 PostForm, 内容大致如下:

      class PostForm extends \yii\base\Model
      {
          // 存储 Post 模型中的字段
          public $title; 
          // 存储 PostExtra 模型中的字段
          public $content;
          // 存储 PostAttachment 模型中的字段
          public $imgUrl;
        
          public function rules()
          {
              // ...
          }
      }
      
    • 一个 Post 对应一个 PostExtra;

    • 一个 Post 对应一个 PostAttachment;

    帖子修改操作的控制器代码大致如下:

    class PostController extends \yii\web\Controller
    {
        public function actionUpdate($id)
        {
            $post = Post::findOne($id);
            $extra = $post->extra;
            $attachment = $post->attachment;
    
            $postForm = new PostForm();
            $postForm->title = $post->title;
            $postForm->content = $extra->content;
            $postForm->imgUrl = $attachment->imgUrl;
    
            if ($postForm->load(Yii::$app->request->post()) && $postForm->validate()) {
                // 写入修改后的数据
            }
    
            return $this->render('update', ['postForm' => $postForm]);
        }
    }
    

    “多模型同时输入”也可以。你觉得“别扭”的三个 &&:

    • load() && load()
    • validate() && validate()
    • save() && save()

    前两个是必须的,最后一个可以放在一个事务内。过程大致如下:

    class PostController extends \yii\web\Controller
    {
        public function actionUpdate($id)
        {
            $post = Post::findOne($id);
            $extra = $post->extra;
            $attachment = $post->attachment;
    
            if (
                $post->load(Yii::$app->request->post()) 
                && $post->validate()
                && $extra->load(Yii::$app->request->post()) 
                && $extra->validate()
                && $attachment->load(Yii::$app->request->post()) 
                && $attachment->validate()
            ) {
                $transaction = Yii::$app->db->beginTransaction();
                try {
                    if (!$post->save(false)) {
                        throw new \yii\db\Exception('Failed to insert xxx.');
                    }
                    if (!$extra->save(false)) {
                        throw new \yii\db\Exception('Failed to insert xxx.');
                    }
                    if (!$attachment->save(false)) {
                        throw new \yii\db\Exception('Failed to insert xxx.');
                    }
            
                    $transaction->commit();
    
                    return $this->redirect('index');
    
                } catch(\Exception $e) {
                    $transaction->rollBack();
                    throw $e;
                }
            }
    
            return $this->render('update', [
                'post' => $post,
                'extra' => $extra,
                'attachment' => $attachment,
            ]);
        }
    }
    
    1 条回复
    回复于 2017-08-07 23:55 回复

    逆了天的完美回答。

  • 回答于 2017-12-17 17:59 举报

    涉及多个表的操作,其实可以用一个 Form model去封装一下。。但是我看官方的教程,直接就写在了控制器里!!其实大同小异了。条条大路通罗马!!

  • 回答于 2018-01-06 22:35 举报

    模型和业务逻辑联系在了一起,nice

您需要登录后才可以回答。登录 | 立即注册
mydzoo
总监

mydzoo

注册时间:2017-01-05
最后登录:2022-03-29
在线时长:53小时40分
  • 粉丝4
  • 金钱2075
  • 威望10
  • 积分2705

热门问题