• Laravel Vuejs 实战:开发知乎 (11)实现选择话题整个流程


    修改QuestionController.php如下:

    1.处理Topic:

      1 /**
      2  * @param array $topics
      3  * @return array
      4  */
      5 private function normalizeTopics(array $topics)
      6 {
      7     //返回topic的id序列,如果不是数字,则强制认为是数据库中的topic的id,
      8     //这样虽然会漏掉用户如果设置的topic就是数字的情况,但是因为是测试,所以暂时忽略
      9     $normalizedTopics = collect($topics)->map(function ($topic) {
     10         if (is_numeric($topic))//是数字
     11         {
     12             //在数据库中找id
     13             $num_topic = Topic::query()->find($topic);
     14             if (isset($num_topic) && $num_topic->count() > 0) //在数据库中找得到id
     15             {
     16                 //因为是找到了 且是从question处提交,其内部的question_count应该增加1个
     17                 $num_topic->increment('questions_count');
     18                 //返回id
     19                 return (int)$num_topic->id;
     20             }
     21         }
     22         //否则创建一个新的topic
     23         //再之前先判断是否找得到,因为有时候重复提交,select2在提交的数据中不为数字,但是实际上数据库中已经有值
     24         $already = Topic::query()->select('id', 'name')->where('name', '=', $topic);
     25 
     26         if ($already->count() > 0) {
     27             //因为是找到了 且是从question处提交,其内部的question_count应该增加1个
     28             $already->increment('questions_count');
     29             //返回id
     30             return $already->first()->id;
     31         }
     32         $data_of_topic = [
     33             'name' => $topic,//目前view中topic只有一个选择框,没有设置content的输入框
     34             'questions_count' => 1,//因为是找到了 且是从question处提交,其内部的question_count应该初始化为1个
     35         ];
     36         //入库
     37         $newTopic = Topic::create($data_of_topic);
     38         //返回id
     39         return $newTopic->id;
     40     })->toArray();
     41 
     42     return $normalizedTopics;
     43 }
     44 

    2.更新关联:

      1  /**
      2      * @param QuestionStoreRequest $request
      3      * @return IlluminateHttpRedirectResponse
      4      */
      5     public function store(QuestionStoreRequest $request)//依赖注入QuestionStoreRequest实例
      6     {
      7         //
      8 //        $data = $request->validate([
      9 //            'title' => 'required|min:8',
     10 //            'content' => 'required|min:28',
     11 //        ]);
     12         //存储topics
     13         $topics = $this->normalizeTopics($request->get('topics'));
     14         //初始化question要用到的数据
     15         $data = $request->all();
     16         $data['user_id'] = auth()->user()->id;
     17 
     18         $question = Question::create($data);
     19         //使用我们再question model里面添加的topics方法获得 topics关联,再使用attach方法
     20 
     21         $question->topics()->attach($topics);
     22 
     23         return redirect()->route('questions.show', $question);
     24     }
     25 

    参考模型关联的官方文档:我们使用了attach方法,更多关于attach,detach,sync方法的介绍可以看:Laravel 模型关联attach,save,sync方法参数类型验证laravel 多对多关联 attach detach sync

    代码:$question->topics()->attach($topics); 解析:

    根据Question.php模型下的topics方法,关联信息的表是questions_topics,如果不设置,会有一个默认值

      1 public function topics()
      2 {
      3     return $this->belongsToMany(
      4         Topic::class,
      5         'questions_topics' //表名我设置的是questions_topics,可能不是系统自动解析的question_topic
      6     )->withTimestamps();//withTimestamps操作questions_topics表中create_at及updated_at字段的
      7 }
      8 

    操作questions_topics表,使用attach方法,向表中添加question_id 对应的 $topics数组里的id数组值。如图:批注 2020-02-29 003329

    由于当前显示的页面中不够完善,我们想看到添加的question的topics信息,所以在QuestionController.php的show方法更改如下以提供view需要的数据:

      1 /**
      2  * @param Question $question
      3  * @return IlluminateContractsViewFactory|IlluminateViewView
      4  */
      5 public function show(Question $question)
      6 {
      7     //使用关系关联加载,with方法会将分类之下的商品一起查询出来,而且不会出现N+1影响性能的问题
      8     $question->with('topics')->get();
      9 
     10     return view('questions.show', compact('question'));
     11 }
     12 
     13 

    关于with方法的介绍:

    预加载

    Laravel的Eloquent ORM 关联关系中的with用法

    然后修改show.blade.php文件如下:

      1 @extends('layouts.app')
      2 
      3 @section('content')
      4 
      5     <div class="container">
      6         <div class="row">
      7             <div class="col-md-8 col-md offset-2">
      8                 <div class="card">
      9                     <div class="card-header">
     10                         {{ $question->title }}
     11                         @forelse($question->topics as $topic)
     12                             <button class="btn btn-secondary float-md-right m-1">{{ $topic->name }}</button>
     13                         @empty
     14                             <p class="text text-warning float-md-right"> "No Topics"</p>
     15                         @endforelse
     16                     </div>
     17                     <div class="card-body">
     18                         {!! $question->content !!}
     19                     </div>
     20                 </div>
     21             </div>
     22         </div>
     23     </div>
     24     <style scoped>
     25         .card-body img {
     26              100%;
     27         }
     28     </style>
     29 @endsection

    最后效果如下:

    批注 2020-02-29 005052

  • 相关阅读:
    扩展欧几里得
    Android中进行流量统计
    经常使用的DB2命令(2)
    构建下一代服务载体,智能设备这座宝藏该怎么挖?
    Oracle 11g新特性虚拟列分区
    Convert Sorted List to Binary Search Tree
    c#高效的线程安全队列ConcurrentQueue<T>(上)
    String、StringBuffer与StringBuilder之间区别
    C# 中的委托和事件
    利用C#自带组件强壮程序日志
  • 原文地址:https://www.cnblogs.com/dzkjz/p/12381296.html
Copyright © 2020-2023  润新知