[Laravel] 07 - Project: functions in Controller

故事背景


1、項目預覽

From: https://www.imooc.com/video/12521php

 

 

 

表單操做


1、新增信息

既然是操做,天然會想到:控制器。html

  • 控制器 

[1] 路由 ----> 函數 create( )laravel

Route::group(['middleware' => ['web']], function () {

    Route::get('student/index',       ['uses' => 'StudentController@index']);
    Route::any('student/create',      ['uses' => 'StudentController@create']);
    Route::any('student/save',        ['uses' => 'StudentController@save']);
    Route::any('student/update/{id}', ['uses' => 'StudentController@update']);
    Route::any('student/detail/{id}', ['uses' => 'StudentController@detail']);
    Route::any('student/delete/{id}', ['uses' => 'StudentController@delete']);
});

[app/Http/StudentController.php]web

    // 添加頁面
    public function create(Request $request)
    {
        $student = new Student();

        if ($request->isMethod('POST')) {

-----------------------------------------------------------------------
// 1. 控制器驗證 // 2. Validator類驗證
------------------------------------------------------------------------
$data = $request->input('Student'); if (Student::create($data) ) { return redirect('student/index')->with('success', '添加成功!'); } else { return redirect()->back(); } } return view('student.create', [ 'student' => $student ]); }

 

[2] 函數 create( ) return --> 視圖 數據庫

 

  • 表單提交

以上只是打開create頁面,這裏纔是submit。segmentfault

   // 保存添加
    public function save(Request $request)
    {
        $data = $request->input('Student');

        $student = new Student();
        $student->name = $data['name'];
        $student->age  = $data['age'];
        $student->sex  = $data['sex'];

        if ($student->save()) {
            return redirect('student/index');  // 路由重定向
        } else {
            return redirect()->back();      // 返回上一個請求頁面
        }

    }

 

[1] Submit 表單內容提交的過程是怎樣的?api

Goto: [PHP] 03 - Form & Inputsession

[2] 也能夠默認將邏輯寫在save中,也便是action中採用默認形式(設置爲空字符串)app

 

  • 提交結果

[1] 表單空內容提交,可採用「中間件」方法解決,便不會直接報系統錯誤。框架

[2] tokenMIsMatchException錯誤的解決方案:

<form class="form-horizontal" method="post" action="">

    {{ csrf_field() }}  該字段:生成了隱藏的input表單,自帶token字段

    <div class="form-group">
        <label for="name" class="col-sm-2 control-label">姓名</label>

        <div class="col-sm-5">
            <input type="text" name="Student[name]"
                   value="{{ old('Student')['name'] ? old('Student')['name'] : $student->name }}"
                   class="form-control" id="name" placeholder="請輸入學生姓名">
        </div>
        <div class="col-sm-5">
            <p class="form-control-static text-danger">{{ $errors->first('Student.name') }}</p>
        </div>
    </div>
    <div class="form-group">
        <label for="age" class="col-sm-2 control-label">年齡</label>

        <div class="col-sm-5">
            <input type="text" name="Student[age]"
                   value="{{ old('Student')['age'] ?  old('Student')['age'] : $student->age }}"
                   class="form-control" id="age" placeholder="請輸入學生年齡">
        </div>
        <div class="col-sm-5">
            <p class="form-control-static text-danger">{{ $errors->first('Student.age') }}</p>
        </div>
    </div>
    <div class="form-group">
        <label class="col-sm-2 control-label">性別</label>

        <div class="col-sm-5">
            @foreach($student->sex() as $ind=>$val)
                <label class="radio-inline">
                    <input type="radio" name="Student[sex]"
                           {{ isset($student->sex) && $student->sex == $ind ? 'checked' : ''  }}
                           value="{{ $ind }}"> {{ $val }}
                </label>
            @endforeach
        </div>
        <div class="col-sm-5">
            <p class="form-control-static text-danger">{{ $errors->first('Student.sex') }}</p>
        </div>
    </div>
    <div class="form-group">
        <div class="col-sm-offset-2 col-sm-10">
            <button type="submit" class="btn btn-primary">提交</button>
        </div>
    </div>
</form>

[3] 判斷Session中的參數來控制UI片斷的顯示。

<!-- 成功提示框 -->
@if (Session::has('success'))
<div class="alert alert-success alert-dismissible" role="alert">
    <button type="button" class="close" data-dismiss="alert" aria-label="Close">
        <span aria-hidden="true">&times;</span>
    </button>
    <strong>成功!</strong> {{ Session::get('success') }}
</div>
@endif

<!-- 失敗提示框 -->
@if (Session::has('error'))
<div class="alert alert-danger alert-dismissible" role="alert">
    <button type="button" class="close" data-dismiss="alert" aria-label="Close">
        <span aria-hidden="true">&times;</span>
    </button>
    <strong>失敗!</strong> {{ Session::get('error') }}
</div>
@endif

 

 

2、數據驗證

  • 出錯提示視圖

[1] 獲取$error變量後,循環打印出。

@if (count($errors))

    <div class="alert alert-danger">
        <ul>
            <li>{{ $errors->first() }}</li>
        </ul>
    </div>

    <div class="alert alert-danger">
        <ul>
            @foreach($errors->all() as $error)
            <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>

@endif

[2] 視圖效果以下。 

[3] 那麼,$error 從哪裏來?

經過中間件將出錯信息綁定到全部的視圖中,視圖中可直接獲取。 

 

  •  控制器驗證法

Ref: https://www.imooc.com/video/12522

 // 1. 控制器驗證
            $this->validate($request, [
                'Student.name' => 'required|min:2|max:20',
                'Student.age'  => 'required|integer',
                'Student.sex'  => 'required|integer',
            ], [
                'required'     => ':attribute 爲必填項',
                'min'          => ':attribute 長度不符合要求',
                'integer'      => ':attribute 必須爲整數',
            ], [
                'Student.name' => '姓名',
                'Student.age'  => '年齡',
                'Student.sex'  => '性別',
            ]);

[1] $this:當前控制器;validate驗證方法;

[2] 以下提示不夠友好,須要替換下內容;

[3] 中間件的效果

若是沒有驗證經過,中間件ShareErrorsFromSession開始發揮做用:

(1) 框架會拋出一個異常;

(2) 異常被自動捕獲,重定向到上一個頁面;

(3) 錯誤信息被存在session中,且綁定到視圖上;

因此,返回的「上一個頁面"就能夠直接在視圖中得到出錯信息 by $error變量。

    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,\Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
        ],

        'api' => [
            'throttle:60,1',
        ],
    ];

  

  • Validator類驗證法 

\Validator全局的。

 // 2. Validator類驗證
            $validator = \Validator::make($request->input(), [
                'Student.name' => 'required|min:2|max:20',
                'Student.age'  => 'required|integer',
                'Student.sex'  => 'required|integer',
            ], [
                'required'     => ':attribute 爲必填項',
                'min'          => ':attribute 長度不符合要求',
                'integer'      => ':attribute 必須爲整數',
            ], [
                'Student.name' => '姓名',
                'Student.age'  => '年齡',
                'Student.sex'  => '性別',
            ]);

            if ($validator->fails()) {
                return redirect()->back()->withErrors($validator)->withInput();
            }

 

  • 數據保持

[1] 點擊提交後,若是執行失敗,註冊的信息保留住,方便查看到底錯在了哪裏。

在返回上一個頁面的同時並填充原始的信息($request)。

if ($validator->fails()) {
  return redirect()->back()->withErrors($validator)->withInput();
}

[2] 對應地,使用以下old方法來提取withInput()中保存的數據。

  <div class="form-group">
        <label for="name" class="col-sm-2 control-label">姓名</label>

        <div class="col-sm-5">
            <input type="text" name="Student[name]"
                   value="{{ old('Student')['name'] ? old('Student')['name'] : $student->name }}"
                   class="form-control" id="name" placeholder="請輸入學生姓名">
        </div>
<div class="col-sm-5"> <p class="form-control-static text-danger">{{ $errors->first('Student.name') }}</p> </div> </div>

 

 

3、經過模型處理性別 

  • 模型中的性別屬性

問題,致使數據庫中存儲數據的形式是數字。其實這也並不是是"大問題」。

  

Self 與 This

在訪問PHP類中的成員變量或方法時,若是被引用的變量或者方法被聲明成const(定義常量)或者static(聲明靜態),那麼就必須使用操做符::,

反之若是被引用的變量或者方法沒有被聲明成const或者static,那麼就必須使用操做符->。

一句話,self是引用靜態類的類名,而$this是引用非靜態類的實例名。

 

  • Model中增長屬性

性別屬性實際上是枚舉類屬性的一個典型例子,在此做爲典型案例進行分析。

但願:只修改這裏,相應的部分都能自動改變。

    public function sex($ind = null)
    {
        $arr = [
            self::SEX_UN   => '未知',
            self::SEX_BOY  => '男',
            self::SEX_GRIL => '女',
        ];

        if ($ind !== null) {
            return array_key_exists($ind, $arr) ? $arr[$ind] : $arr[self::SEX_UN];
        }

        return $arr;
    }

  

  • ’學生列表‘View中獲取屬性

學生列表中作出調整。

<tbody>
  @foreach($students as $student)
  <tr>
    <th scope="row">{{ $student->id }}</th>
    <td>{{ $student->name }}</td>
    <td>{{ $student->age }}</td>
    <td>{{ $student->sex($student->sex) }}</td>  # 這裏提取到的就是字符串了
    <td>{{ date('Y-m-d', $student->created_at) }}</td>
    <td>
      <a href="{{ url('student/detail', ['id' => $student->id]) }}">詳情</a>
      <a href="{{ url('student/update', ['id' => $student->id]) }}">修改</a>
      <a href="{{ url('student/delete', ['id' => $student->id]) }}"
        onclick="if (confirm('肯定要刪除嗎?') == false) return false;">刪除</a>
    </td>
  </tr>
  @endforeach
</tbody>

 

  • '建立'View中獲取屬性

Create界面原始寫法,就是一組 radio button。

取出student中的key和value:as $ind => $val

 

 

4、修改表單

Ref: https://www.imooc.com/video/12524

咱們的思路是:儘可能利用「添加表單」的邏輯和頁面。

  • 添加連接
<tbody>
  @foreach($students as $student)
  <tr>
                    <th scope="row">{{ $student->id }}</th>
                    <td>{{ $student->name }}</td>
                    <td>{{ $student->age }}</td>
                    <td>{{ $student->sex($student->sex) }}</td>
                    <td>{{ date('Y-m-d', $student->created_at) }}</td>
                    <td>
                        <a href="{{ url('student/detail', ['id' => $student->id]) }}">詳情</a>
                        <a href="{{ url('student/update', ['id' => $student->id]) }}">修改</a>
                        <a href="{{ url('student/delete', ['id' => $student->id]) }}"
                                onclick="if (confirm('肯定要刪除嗎?') == false) return false;">刪除</a>
                    </td>
  </tr>
  @endforeach
</tbody>

  

  • 修改頁面

[1] 控制器 ----> 「頁面」,得到了模型的數據:$student

   public function update(Request $request, $id)
    {
# 先得到表單
$student = Student::find($id); if ($request->isMethod('POST')) {  // 來自client的POST,攜帶了「edit」信息 $this->validate($request, [ 'Student.name' => 'required|min:2|max:20', 'Student.age' => 'required|integer', 'Student.sex' => 'required|integer', ], [ 'required' => ':attribute 爲必填項', 'min' => ':attribute 長度不符合要求', 'integer' => ':attribute 必須爲整數', ], [ 'Student.name' => '姓名', 'Student.age' => '年齡', 'Student.sex' => '性別', ]);
# 這裏得到了數據,有待」視圖「去使用$student
$data = $request->input('Student'); $student->name = $data['name']; $student->age = $data['age']; $student->sex = $data['sex']; if ($student->save()) { return redirect('student/index')->with('success', '修改爲功-' . $id); } } return view('student.update', [ 'student' => $student ]); }

 

Ref:laravel的$request->input()和$request->get()有什麼區別?

Ref:Laravel 5 $request->input vs Input::get

走的流程不一樣
input獲取數據的流程是把post過來的數據與URL裏的Query合併,而後用helper裏的data_get方法去取數據

/* implement */

 

[2] 「頁面」部分

old表明"最新的數據「,若是是edit,也就沒有」最新數據「這麼一說,old裏就爲空。那麼就從模型student中取數據。

value="{{ old('Student')['name'] ? old('Student')['name'] : $student->name }}"

以上代碼依次在age,gender等其餘屬性處作相應的調整。

[gender]

<div class="col-sm-5">   @foreach($student->sex() as $ind=>$val)   <label class="radio-inline">     <input type="radio" name="Student[sex]"       {{ isset($student->sex) && $student->sex == $ind ? 'checked' : '' }}  // 遍歷了各個枚舉,而後選中額加個checked。       value="{{ $ind }}"> {{ $val }}   </label>   @endforeach </div>

 

 

5、詳情查看 

  • 控制器
public function detail($id)
{
  $student = Student::find($id);

  return view('student.detail', [
    'student' => $student
  ]);
}

 

  • 控制器 ----> 視圖
@extends('common.layouts')

@section('content')

    <div class="panel panel-default">
        <div class="panel-heading">學生詳情</div>

        <table class="table table-bordered table-striped table-hover ">
            <tbody>
            <tr>
                <td width="50%">ID</td>
                <td>{{ $student->id }}</td>
            </tr>
            <tr>
                <td>姓名</td>
                <td>{{ $student->name }}</td>
            </tr>
            <tr>
                <td>年齡</td>
                <td>{{ $student->age }}</td>
            </tr>
            <tr>
                <td>性別</td>
                <td>{{ $student->sex($student->sex) }}</td>
            </tr>
            <tr>
                <td>添加日期</td>
                <td>{{ date('Y-m-d', $student->created_at) }}</td>
            </tr>
            <tr>
                <td>最後修改</td>
                <td>{{ date('Y-m-d', $student->updated_at) }}</td>
            </tr>
            </tbody>
        </table>
    </div>
@stop

 

 

6、刪除信息

  •  刪除模型中的數據
    public function delete($id)
    {

        $student = Student::find($id);

        if ($student->delete()) {
            return redirect('student/index')->with('success', '刪除成功-' . $id);
        } else {
            return redirect('student/index')->with('error', '刪除失敗-' . $id);
        }
    }

 

  • 刪除確認框

刪除不須要專門的刪除頁面,利用onClick方法便可。

            <tbody>
                @foreach($students as $student)
                <tr>
                    <th scope="row">{{ $student->id }}</th>
                    <td>{{ $student->name }}</td>
                    <td>{{ $student->age }}</td>
                    <td>{{ $student->sex($student->sex) }}</td>
                    <td>{{ date('Y-m-d', $student->created_at) }}</td>
                    <td>
                        <a href="{{ url('student/detail', ['id' => $student->id]) }}">詳情</a>
                        <a href="{{ url('student/update', ['id' => $student->id]) }}">修改</a>
                        <a href="{{ url('student/delete', ['id' => $student->id]) }}" onclick="if (confirm('肯定要刪除嗎?') == false) return false;">刪除</a>
                    </td>
                </tr>
                @endforeach
            </tbody>

  

本項目剖析到此結束。

相關文章
相關標籤/搜索