iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 6
0
Modern Web

Laravel 與 Redis教程系列 第 3

Laravel 教程 DAY 6 - 實作入門 - 2

  • 分享至 

  • xImage
  •  

本篇介紹

接續上篇建立完migration,本日將完成文章的CRUD

前言

今天就先不太多廢話了,趕緊完成CRUD吧!
本篇內容略多...

Model

在上一篇的內容,有提到migration的建立與資料遷移。現在我們打開app\Post.php,在model的class內新增欄位,並給予欄位批量賦值的修飾:

class Post extends Model
{
    protected $fillable = [
        'name', 'title', 'content',
    ];
}
  • 批量賦值:model可利用「create」方法將array型態的資料進行模型(實體)的新增,而一般的「save」方法僅能進行單一屬性(欄位)設定,例如:
// create方法
$data = [
    'column_1' => '...',
    'column_2' => '...',
];
Post::create($data);

// save方法
$post = new Post;
$post->column_1 = '...';
$post->column_2 = '...';
$post->save();

※當然,model內還有許多對欄位的屬性設定,比如指定model對應的資料表 (若未指定,會預設指向對應名稱的資料表,如:Post→posts)

protected $table = 'table_name';

View、Controller、Route的緊密相連

為何會一起講解畫面、路由與controller呢?因為當你指定某個URL來呼叫頁面或API時,路由檔會先檢查該URL是否被定義,有被定義的話則會執行該路由所指定controller的function;若沒定義就會報錯。例如

  • Route
// 透過GET方法,導向「/test」,執行TestController的test function,並回傳某個畫面
Route::get('/test', 'TestController@test');
  • Controller
// 進入test function後,回傳「resources\views\test.blade.php」的頁面

class TestController extends Controller
{
    public function test()
    {
        return view('test');
    }
}

講解完後,來實際操作吧!

在command輸入以下指令為我們建立文章的controller

php artisan make:controller PostController --resource
  • 「--resource」是透過artisan為controller建立所有對應RESTful API的function

routes\web.php中,定義新路由:

Route::resource('post', 'PostController');
  • 利用Route的resource方法,依據PostController內的每個function,各自建立一支符合RESTful API的路由 (GET、POST、PUT/PATCH、DELETE),並以post作為路由前綴修飾,如:/post/create

  • 可在command輸入「php artisan route:list」查看路由表,可以看見resource幫我們建立了所有function對應的路由

為了避免views資料夾因為頁面太多而雜亂,因此先在resources\views底下建立「post」資料夾,並在posts內建立「index.blade.php」,用來顯示文章列表:接著在command輸入以下指令

php artisan make:auth
  • 這個指令會為我們建立Laravel的驗證機制(Auth),但本篇暫時不提User的部分,我們擇日再談。使用這指令只是為了讓它先幫我們建立一個共同的layout而已。此時你會看到resources\views多了一個layouts資料夾,裡面有個「app.blade.php」,這檔案能夠當作許多頁面的「主視圖 (master page)」,也就是當作其他子視圖的共用模板,這樣可以省下些許前端設計的麻煩。

  • 副檔名「.blade.php」是讓這個檔案能使用Laravel的Blade模板,它能使畫面的開發上更加便利,且不需使用「<?php」的標籤

編輯app\Http\Controllers\PostController.php

use App\Post;

class PostController extends Controller
{
    // ...略
    public function index()
    {
        $datas = Post::get();
        return view('post.index', compact('datas'));
    }

    // ...略
    public function show($id)
    {
        $data = Post::find($id);
        return view('post.show', compact('data'));
    }
}
  • 記得use App\Post
  • 利用Post這個model取出所有文章的資料,並藉由compact夾帶資料,回傳給前端,讓前端得以使用blade進行處理
  • show function是藉由路由傳入的id,找出該id的文章,並回傳給show頁面
  • find是透過「主鍵」尋找model中的資料

編輯index.blade.php:

@extends('layouts.app')

@section('content')
    <a href="/post/create">新增文章</a>
    <div align="center">
        @foreach ($datas as $key => $data)
            <a href="/post/{{ $data->id }}">{{ $data->title }}</a> <br />
            作者:{{ $data->name }} <br />
            內容:{{ $data->content }} <br />
        @endforeach
    </div>
@endsection
  • extends是讓index.blade.php繼承layouts\app.blade.php的模板
  • section是自定義的一個區塊,這邊將內容都放在content這區塊中,而在app.blade.php中,可藉由「@yield('content')」呼叫所有繼承它的子視圖中,名叫「content」的區塊
  • 利用blade的@foreach,顯示controller回傳的datas變數中,各筆資料的所有欄位

建立show.blade.php

@extends('layouts.app')

@section('content')
    姓名:{{ $data->name }} <br />
    標題:{{ $data->title }} <br />
    內容:{{ $data->content }} <br />
    <a href="/post/{{ $data->id }}/edit" >
        <button>編輯</button>
    </a>

    <form action="/post/{{ $data->id }}" method="POST">
        {{ csrf_field() }}
        {{ method_field('DELETE') }}
        <a href="">
            <button>刪除</button>
        </a>
    </form>
@endsection
  • 使用html的form元素,導向/post/{id}的路由
  • {{ csrf_field() }} 為避免網站遭受CSRF攻擊,若無則Laravel會跳警告
  • {{ method_field('DELETE') }} 是夾帶DELETE方法,進行刪除的動作

修改PostController的destroy function

public function destroy($id)
{
    Post::destroy($id);
    return redirect('/post');
}
  • 透過主鍵刪除該文章,並重新導向至/post

建立create.blade.php,並編輯

@extends('layouts.app')

@section('content')
    <form action="/post" method="POST">
        姓名:<input type="text" name="name" /><br />
        標題:<input type="text" name="title" /><br />
        內容:<textarea name="content"></textarea>
        {{ csrf_field() }}
        <input type="submit" value="送出" />
    </form>
@endsection

修改PostController的create 及 store function

// ...略
public function create()
{
    return view('post.create');
}

// ...略
public function store(Request $request)
{
    $data = $request->all();
    Post::create($data);
    return redirect('/post');
}
  • 回傳view\post的create頁面
  • store function中,將前端傳送的值由Request類別接收,利用model的create方法儲存為一個資料模型 (寫入資料庫),並重新導向至/post

修改PostController的edit 與 update function

public function edit($id)
{
    $data = Post::find($id);
    return view('post.edit', compact('data'));
}

public function update(Request $request, $id)
{
    $data = $request->all();
    Post::find($id)->update($data);
    return redirect('/post/'.$id);
}
  • edit function藉由路由傳入的id作為參數(文章id),並由該id尋找文章,回傳給edit頁面
  • update function接收到前端的值後,利用find方法尋找該文章,並更新內容,最後導向至/post/{id} 的頁面 (show.blade.php)

新增edit.blade.php並編輯

@extends('layouts.app')

@section('content')
    <form action="/post/{{ $data->id }}" method="POST">
        姓名:<input type="text" name="name" value="{{ $data->name }}" /> <br />
        標題:<input type="text" name="title" value="{{ $data->title }}" /> <br />
        內容:<textarea name="content">{{ $data->content }}</textarea>
        {{ csrf_field() }}
        {{ method_field('PATCH') }}
        <input type="submit" value="送出" />
    </form>
@endsection
  • 透過form導向至文章更新的路由
  • {{ method_field('PATCH) }} 讓事件夾帶PATCH方法傳輸資料
  • PUT/PATCH都是更新,但PUT是重新覆蓋整筆資料,PATCH是做部分更新

這樣文章CRUD就結束了!下篇開始會陸續講解會員部分與model關聯


上一篇
Laravel 教程 DAY 5 - 實作入門 - 1
下一篇
Laravel 教程 DAY 12 - Redis概述
系列文
Laravel 與 Redis教程4
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
eric19740521
iT邦新手 1 級 ‧ 2020-08-27 17:51:59

為何edit.blade.php資料編輯,照你的方式是對的??


@extends('members.base')

@section('main')
會員--修改
<form action="{{action('MemberController@update', $member->id , $member->mem_name)}}" method="put" >
    @csrf 	
    <label>會員名稱:
        <input name="mem_name" value="{{$member->mem_name}}"></input>
    </label><br>
 		
    <input type="submit" value="送出">
</form>
@endsection

用這樣就可以?!

@extends('members.base')

@section('main')
會員--修改
<form action="/members/{{ $member->id }}" method="post" >
    @csrf 	
    <label>會員名稱:
        <input name="mem_name" value="{{$member->mem_name}}"></input>
    </label><br>
 	{{ method_field('PATCH') }}	
    <input type="submit" value="送出">
</form>
@endsection

我大概了解意思了!!
用POST方法傳送,然後再送出一個隱藏屬性PUT
讓laravel,幫你處理路由


@extends('members.base')

@section('main')
會員--修改
<!-- /members/{{ $member->id }} -->
<form action="{{ route('members.update', $member->id)}}" method="post" >
	<!-- _token 隱藏欄位-->
    @csrf	  
 	
    <label>會員名稱:
        <input name="mem_name" value="{{$member->mem_name}}"></input>
    </label><br>
	
	<!--PUT/PATCH	/members/{member}	update		members.update -->
	<!--用POST方法傳送,然後再送出一個隱藏屬性PUT -->
	@method('PUT')
    <input type="submit" value="送出">
</form>
@endsection

我要留言

立即登入留言