zoukankan      html  css  js  c++  java
  • Laravel Vuejs 实战:开发知乎 (17)实现提交答案

    1.添加路由 并 处理AnswerController内逻辑:

    路由:向web.php中添加:

      1 #region 回答路由CRUD
      2 
      3 //查看回答 以及 回答的form 都是在questions详细内容页面
      4 
      5 //提交回答
      6 Route::post('questions/{question}/answers', 'AnswerController@store')->name('answers.store');
      7 
      8 //更新回答
      9 
     10 
     11 //删除回答
     12 
     13 
     14 #endregion
     15 
      1 <?php
      2 
      3 /*
      4 |--------------------------------------------------------------------------
      5 | Web Routes
      6 |--------------------------------------------------------------------------
      7 |
      8 | Here is where you can register web routes for your application. These
      9 | routes are loaded by the RouteServiceProvider within a group which
     10 | contains the "web" middleware group. Now create something great!
     11 |
     12 */
     13 
     14 Route::get('/', function () {
     15     return view('welcome');
     16 });
     17 
     18 Auth::routes(['verify' => true]);
     19 
     20 Route::get('/home', 'HomeController@index')->name('home');
     21 
     22 Route::resource('questions', 'QuestionController');
     23 
     24 
     25 #region 回答路由CRUD
     26 
     27 //查看回答 以及 回答的form 都是在questions详细内容页面
     28 
     29 //提交回答
     30 Route::post('questions/{question}/answers', 'AnswerController@store')->name('answers.store');
     31 
     32 //更新回答
     33 
     34 
     35 //删除回答
     36 
     37 
     38 #endregion
     39 
     40 
    web.php

    AnswerController.php最后更新见文末

    2.在question详情内页 添加提交回答的form

    最后更新见文末 show.blade.php

    3.提交后由于要给Question和User模型内赋值 answer_id 所以在$fillable属性里加上'answer_id':

    不赋值!见后文Pointing up根据 一对多关系处说明。不存所以表里之前的字段要删除,也就更不可能赋值了

    在处理一对多的时候

    Php Laravel框架 多表关系处理 之 Eloquent一对多关系处理

    Laravel One to Many Eloquent Relationship Tutorial

    多对多的时候:

    Laravel中的 Pivot 表与多对多关系s

    一对多关系,在创建answer模型的时候,需要更新user 和 question 里面的 answer_id,

    不需要更新!见后文Pointing up根据 一对多关系处说明。不存所以表里之前的字段要删除,也就更不可能需要更新了

    之前忘了在anwers 的 migration里加外键;

    【模型之间通过模型关联方法 已经默认配置了外键 讲解:一对多

    laravel模型表建立外键约束的使用:

    模型:

      1 //表->posts
      2 class Post extends Model
      3 {
      4     //关联用户:
      5     public function user(){
      6         //belongsTo,第一个参数:外键表,第二个:当前表的外键,第三个:外渐表的主键。
      7         //如果第二个是名词+id,第三个是:id。后面的两个参数可以省略:
      8         // return $this->belongsTo('AppUser');
      9         return $this->belongsTo('AppUser','user_id','id');
     10     }
     11 }
     12 

    视图中的调用:下面的会输出:posts表中user_id对应的user表中的id的name值

      1 <a href="#">{{$post->user->name}}</a></p>


    现在加上,执行命令:

      1 php artisan make:migration add_foreign_key_relationship_to_answers_table --table=answers

    注意是answers表;

      1 <?php
      2 
      3 use IlluminateDatabaseMigrationsMigration;
      4 use IlluminateDatabaseSchemaBlueprint;
      5 use IlluminateSupportFacadesSchema;
      6 
      7 class AddForeignKeyRelationshipToAnswersTable extends Migration
      8 {
      9     /**
     10      * Run the migrations.
     11      *
     12      * @return void
     13      */
     14     public function up()
     15     {
     16         Schema::table('answers', function (Blueprint $table) {
     17             //
     18             $table->foreign('user_id')->references('id')->on('users');
     19             $table->foreign('question_id')->references('id')->on('questions');
     20         });
     21     }
     22 
     23     /**
     24      * Reverse the migrations.
     25      *
     26      * @return void
     27      */
     28     public function down()
     29     {
     30         Schema::table('answers', function (Blueprint $table) {
     31             //
     32             $table->dropForeign('answers_user_id_foreign');
     33             $table->dropForeign('answers_question_id_foreign');
     34         });
     35     }
     36 }
     37 
     38 
    2020_02_29_143522_add_foreign_key_relationship_to_answers_table.php

    注意foreign key的命名:answers_user_id_foreign  查阅: Foreign Key Constraints 

    然后执行:

      1 php artisan migrate


    Pointing up根据 一对多关系:

    主表不存子表的id:用户不存回答的id,问题不存回答的id,

    子表存储主表的id:回答存储用户的id,回答存储问题的id,并设置外键,可以使用save saveMany associate再save方法;批注 2020-02-29 225253

    具体请查阅: Laravel One to Many Eloquent Relationship Tutorial

    所以我们需要移除之前再Quesiton和User表中的answer_id字段;代码省略

    多对多的表:

    新建立第三个表  还要使用attach sync detach方法操作更新

    以上都必须设置模型关联

    具体请查阅:Laravel Many to Many Eloquent Relationship Tutorial


    show.blade.php:

      1 @extends('layouts.app')
      2 @section('content')
      3     <div class="container">
      4         <div class="row">
      5             <div class="col-md-8 col-md offset-2">
      6                 {{--问题--}}
      7                 <div class="card">
      8                     <div class="card-header">
      9                         {{ $question->title }}
     10 
     11                         @foreach(['success','warning','danger'] as $info)
     12                             @if(session()->has($info))
     13                                 <div class="alert alert-{{$info}}">{{ session()->get($info) }}</div>
     14                             @endif
     15                         @endforeach
     16 
     17                         @can('update',$question)
     18                             <a href="{{ route('questions.edit',$question) }}" class="btn btn-warning">编辑</a>
     19                         @endcan
     20 
     21                         @can('destroy',$question)
     22                             <form action="{{ route('questions.destroy',$question) }}" method="post">
     23                                 @csrf
     24                                 @method('DELETE')
     25                                 <button type="submit" class="btn btn-danger">删除</button>
     26                             </form>
     27                         @endcan
     28 
     29                         @forelse($question->topics as $topic)
     30                             <button class="btn btn-secondary float-md-right m-1">{{ $topic->name }}</button>
     31                         @empty
     32                             <p class="text text-warning float-md-right"> "No Topics"</p>
     33                         @endforelse
     34 
     35                         <p class="text text-info float-md-right"> 已有{{ count($question->answers) }}个回答</p>
     36 
     37                     </div>
     38                     <div class="card-body">
     39                         {!! $question->content !!}
     40                     </div>
     41                 </div>
     42 
     43 
     44                 {{--回答提交form--}}
     45 
     46                 <div class="card mt-2">
     47                     <div class="card-header">
     48                         提交回答
     49                     </div>
     50                     <div class="card-body">
     51                         <form action="{{ route('answers.store',$question) }}" method="post">
     52                         @csrf
     53                         <!-- 回答编辑器容器 -->
     54                             <script id="container" name="content" type="text/plain"
     55                                     style=" 100%;height: 200px">{!! old('content') !!}</script>
     56                             <p class="text text-danger"> @error('content') {{ $message }} @enderror </p>
     57                             <!--提交按钮-->
     58                             <button type="submit" class="btn btn-primary mt-2 float-md-right">提交回答</button>
     59                         </form>
     60                     </div>
     61                 </div>
     62 
     63                 {{--展示答案--}}
     64                 @forelse($question->answers as $answer)
     65                     <div class="card mt-4">
     66                         <div class="card-header">
     67                             <div class="float-left">
     68                                 <img src="{{ $answer->user->avatar }}" class="img-thumbnail imgWrap"
     69                                      style="height: 50px" alt="{{ $answer->user->name }}">
     70                                 <span class="text text-info">{{ $answer->user->name }}</span>
     71                             </div>
     72                             <span class="float-right text text-info m-auto">{{ $answer->updated_at }}</span>
     73                         </div>
     74 
     75                         <div class="card-body">
     76                             {!!  $answer->content  !!}
     77                         </div>
     78                     </div>
     79 
     80                 @empty
     81 
     82                 @endforelse
     83             </div>
     84         </div>
     85     </div>
     86 @endsection
     87 @section('footer-js')
     88     @include('questions._footer_js')
     89 @endsection
    show.blade.php

    QuestionController.php:

      1 <?php
      2 
      3 namespace AppHttpControllers;
      4 
      5 use AppHttpRequestsQuestionStoreRequest;
      6 use AppModelsQuestion;
      7 use AppRepositoriesQuestionRepository;
      8 
      9 
     10 class QuestionController extends Controller
     11 {
     12 
     13     /**
     14      * @var QuestionRepository
     15      */
     16     private $questionRepository;
     17 
     18     public function __construct(QuestionRepository $questionRepository)
     19     {
     20         $this->middleware(
     21             'auth',
     22             [
     23                 'except' =>
     24                     [
     25                         'index',
     26                         'show',
     27                     ]//非注册用户只能查看不能编辑添加更改删除
     28             ]
     29         );
     30 
     31         $this->questionRepository = $questionRepository;
     32     }
     33 
     34 
     35     /** Display a listing of the resource.
     36      * @return IlluminateContractsViewFactory|IlluminateViewView
     37      */
     38     public function index()
     39     {
     40         //
     41         $questions = $this->questionRepository->getQuestionPublished();
     42         return view('questions.index', compact('questions'));
     43     }
     44 
     45 
     46     /**
     47      * @return IlluminateContractsViewFactory|IlluminateViewView
     48      */
     49     public function create()
     50     {
     51         //
     52         return view('questions.create');
     53     }
     54 
     55 
     56     /**
     57      * @param QuestionStoreRequest $request
     58      * @return IlluminateHttpRedirectResponse
     59      */
     60     public function store(QuestionStoreRequest $request)//依赖注入QuestionStoreRequest实例
     61     {
     62         //
     63 //        $data = $request->validate([
     64 //            'title' => 'required|min:8',
     65 //            'content' => 'required|min:28',
     66 //        ]);
     67         //存储topics
     68         $topics = $this->questionRepository->normalizeTopics($request->get('topics'));
     69         //初始化question要用到的数据
     70         $data = $request->all();
     71         $data['user_id'] = auth()->user()->id;
     72 
     73 //        $question=Question::create($data); 被下方代码取代
     74         $question = $this->questionRepository->create($data);
     75 
     76         //使用我们再question model里面添加的topics方法获得 topics关联,再使用attach方法
     77         $question->topics()->attach($topics);
     78 
     79         return redirect()->route('questions.show', $question);
     80     }
     81 
     82 
     83     /**
     84      * @param Question $question
     85      * @return IlluminateContractsViewFactory|IlluminateViewView
     86      */
     87     public function show(Question $question)
     88     {
     89         //使用关系关联加载,with方法会将分类之下的主题一起查询出来,而且不会出现N+1影响性能的问题
     90         $question->with('topics')->get();
     91         //使用关系关联加载,with方法会将分类之下的回答一起查询出来,而且不会出现N+1影响性能的问题
     92         $question->with('answers')->get();
     93 
     94         return view('questions.show', compact('question'));
     95     }
     96 
     97 
     98     /**判断权限 返回视图
     99      * @param Question $question
    100      * @return IlluminateContractsViewFactory|IlluminateHttpRedirectResponse|IlluminateViewView
    101      */
    102     public function edit(Question $question)
    103     {
    104         if (auth()->user()->can('update', $question)) //判断当前用户是否有权编辑更新该question实例
    105         {
    106             //返回编辑视图
    107             return view('questions.edit', compact('question'));
    108         } else {
    109             //返回警告 没有权限
    110             return redirect()->back()->with('warning', '你不能编辑不属于你的问题!');
    111         }
    112     }
    113 
    114 
    115     /** Update the specified resource in storage.
    116      * @param QuestionStoreRequest $questionStoreRequest
    117      * @param Question $question
    118      * @return IlluminateHttpRedirectResponse
    119      */
    120     public function update(QuestionStoreRequest $questionStoreRequest, Question $question)
    121     {
    122         //更新前 判断下权限
    123         if (!(auth()->user()->can('update', $question))) {
    124             //返回警告 没有权限
    125             return redirect()->back()->with('warning', '你不能编辑不属于你的问题!');
    126         }
    127         //取得更新的字段 使用Eloquent提供的update方法执行问题更新
    128         $question->update([
    129             'title' => $questionStoreRequest->get('title'),
    130             'content' => $questionStoreRequest->get('content'),
    131         ]);
    132 
    133 
    134         //topics的操作这时候看起来有点臃肿 可以使用TopicController来管理,暂时省略
    135         //存储topics
    136         $topics = $this->questionRepository->normalizeTopics($questionStoreRequest->get('topics'));
    137         //使用我们再question model里面添加的topics方法获得 topics关联,
    138         //再使用sync方法同步tag 【删除的会被删除掉,没删除的就保留,新的就增加】
    139         $question->topics()->sync($topics);
    140 
    141         //更新完成,跳转回去
    142         return redirect()->back();
    143     }
    144 
    145 
    146     /**Remove the specified resource from storage.
    147      * @param Question $question
    148      * @return IlluminateHttpRedirectResponse
    149      * @throws Exception
    150      */
    151     public function destroy(Question $question)
    152     {
    153         //
    154         if (auth()->user()->can('destroy', $question)) {
    155             $question->delete();
    156             return redirect()->route('questions.index')->with('success', "删除成功!");
    157         }
    158         return redirect()->back()->with('danger', "你不能删除不属于你的问题!");
    159     }
    160 
    161 
    162 }
    163 
    QuestionController.php

    AnswerController.php:

      1 <?php
      2 
      3 namespace AppHttpControllers;
      4 
      5 use AppAnswer;
      6 use AppModelsQuestion;
      7 use IlluminateHttpRequest;
      8 
      9 class AnswerController extends Controller
     10 {
     11 
     12     /**
     13      * AnswerController constructor.
     14      */
     15     public function __construct()
     16     {
     17         //只有登录用户才能回答问题 但是可以查看 和查看提交创建页面,引导用户去注册
     18         $this->middleware(['auth',])->except(['index', 'create', 'show']);
     19     }
     20 
     21     /**
     22      * Display a listing of the resource.
     23      *
     24      * @return IlluminateHttpResponse
     25      */
     26     public function index()
     27     {
     28         //
     29     }
     30 
     31     /**
     32      * Show the form for creating a new resource.
     33      *
     34      * @return IlluminateHttpResponse
     35      */
     36     public function create()
     37     {
     38         //
     39     }
     40 
     41 
     42     /** Store a newly created resource in storage.
     43      * @param Request $request
     44      * @param Question $question
     45      * @return IlluminateHttpRedirectResponse
     46      */
     47     public function store(Request $request, Question $question)
     48     {
     49         //
     50 
     51 
     52         //初始化回答数据
     53         $data = $request->validate([
     54             'content' => 'required|min:30',
     55         ]);
     56         $data['user_id'] = auth()->user()->id;
     57 
     58         $data['question_id'] = $question->id;
     59 
     60         //创建回答入库
     61         $answer = Answer::create($data);
     62         //更新问题里的数据
     63         $question->increment('answers_count');
     64         //更新用户里的数据
     65         auth()->user()->increment('answers_count');
     66         return redirect()->back()->with('success', "回答成功!");
     67     }
     68 
     69     /**
     70      * Display the specified resource.
     71      *
     72      * @param AppAnswer $answer
     73      * @return IlluminateHttpResponse
     74      */
     75     public function show(Answer $answer)
     76     {
     77         //
     78     }
     79 
     80     /**
     81      * Show the form for editing the specified resource.
     82      *
     83      * @param AppAnswer $answer
     84      * @return IlluminateHttpResponse
     85      */
     86     public function edit(Answer $answer)
     87     {
     88         //
     89     }
     90 
     91     /**
     92      * Update the specified resource in storage.
     93      *
     94      * @param IlluminateHttpRequest $request
     95      * @param AppAnswer $answer
     96      * @return IlluminateHttpResponse
     97      */
     98     public function update(Request $request, Answer $answer)
     99     {
    100         //
    101     }
    102 
    103     /**
    104      * Remove the specified resource from storage.
    105      *
    106      * @param AppAnswer $answer
    107      * @return IlluminateHttpResponse
    108      */
    109     public function destroy(Answer $answer)
    110     {
    111         //
    112     }
    113 }
    114 
    AnswerController.php


    Answer.php

      1 <?php
      2 
      3 namespace App;
      4 
      5 use AppModelsQuestion;
      6 use IlluminateDatabaseEloquentModel;
      7 use IlluminateDatabaseEloquentSoftDeletes;
      8 
      9 class Answer extends Model
     10 {
     11     #region 支持软删除添加
     12     use SoftDeletes;
     13     protected $dates = ['deleted_at'];
     14 
     15     #endregion
     16 
     17     protected $fillable = ['user_id', 'question_id', 'content'];
     18 
     19     /** 一个回答只有一个回答主人
     20      * @return IlluminateDatabaseEloquentRelationsBelongsTo
     21      */
     22     public function user()
     23     {
     24         return $this->belongsTo(User::class);
     25     }
     26 
     27     /** 一个回答只针对一个问题
     28      * @return IlluminateDatabaseEloquentRelationsBelongsTo
     29      */
     30     public function question()
     31     {
     32         return $this->belongsTo(Question::class);
     33     }
     34 
     35 }
     36 
    Answer.php

  • 相关阅读:
    苹果新的编程语言 Swift 语言进阶(五)--控制流
    苹果新的编程语言 Swift 语言进阶(四)--字符串和收集类型
    苹果新的编程语言 Swift 语言进阶(三)--基本运算和扩展运算
    苹果新的编程语言 Swift 语言进阶(二)--基本类型
    第一篇 android架构是如何满足设计目标的?
    第三篇 android 应用开发模式之MVC模式及Observer模式
    第二篇 android应用开发模式之模板模式
    为什么带网格(mesh)的模型添加了刚体Rigidbody和MeshCollider,还是会从地板穿过去?
    Mecanim动画模型规范
    HTC Vive 体验的折腾经历
  • 原文地址:https://www.cnblogs.com/dzkjz/p/12386754.html
Copyright © 2011-2022 走看看