Laravel 5.2 三、中間件、視圖與 Blade 模板引擎


一、中間件

Laravel 的 HTTP 中間件提供了對路由的一層過濾和保護。下面模擬一下用中間件驗證后台登錄。

 

1. 創建中間件

cmd 窗口進入項目目錄,使用 artisan 命令創建

php artisan make:middleware AdminLoginVerify

這將在 app/Http/Middleware 目錄創建中間件 AdminLoginVerify

 

在 AdminLoginVerify 類的 handle()方法中添加驗證邏輯:

<?php
namespace App\Http\Middleware;

use Closure;

class AdminLoginVerify
{
    public function handle($request, Closure $next)
    {
        if(!session('admin')){ // 如果沒有登錄則定向到登錄頁
            return redirect('admin/login');
        }
        return $next($request);
    }
}

ok,現在就創建並定義好了驗證登錄的中間件 AdminLoginVerify

 

2. 注冊中間件

在 app/Http/Kernel.php 文件里找到 protected $routeMiddleware 屬性,追加我們的 AdminLoginVerify

protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'can' => \Illuminate\Foundation\Http\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
         // 自定義中間件
        'adminLoginVerify' => \App\Http\Middleware\AdminLoginVerify::class,
    ];

 

3. 添加路由

在 app/Http/routes.php 文件里添加路由:

// 后台首頁路由、退出登錄路由
Route::group(['prefix' => 'admin', 'namespace' => 'Admin', 'middleware' => 'adminLoginVerify'], function(){
    Route::get('index', 'IndexController@index');
    Route::get('logout', 'IndexController@logout');
});

// 后台登錄路由
Route::group(['middleware' => 'web'], function(){
    Route::get('admin/login', 'Admin\IndexController@login');
});

 

這是后台Admin 目錄下 Index 控制器的代碼:

<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;

class IndexController extends Controller{

    // 后台首頁
    public function index(){
        return '<h1>歡迎你,' . session('admin') . '</h1>';
    }

    // 后台登錄
    public function login(){
        session(['admin' => 'mingc']);
        return '<h1>后台登錄</h1>';
    }

    // 退出登陸
    public function logout(){
        session(['admin' => null]);
        return '<h1>退出登錄</h1>';
    }
}

 

4. 模擬登錄

打開瀏覽器,訪問后台登錄頁

好的,訪問后台首頁

現在我們退出登錄

在退出的狀態下,訪問首頁會重定向到登錄頁。

 

二、視圖

1. 渲染視圖,分配數據

方法1.數組鍵值對分配

// 在控制器中
$data = array(
    'title' => 'Laravel',
    'subTitle' => '高效快捷的PHP框架'
);
return view('my_laravel', $data);

// 在模板中
<?php echo $title;?>
<?php echo $subTitle;?>

  

方法2. with 方法鏈分配

// 在控制器中
return view('my_laravel')->with('title', 'Laravel')->with('subTitle', '高效快捷的PHP框架');

// 在模板中(和上面的一樣)
<?php echo $title;?>
<?php echo $subTitle;?>

 

方法3.利用 compact() 函數分配

// 在控制器中
$data = array(
    'title' => 'Laravel',
    'subTitle' => '高效快捷的PHP框架'
);
$content = 'Laravel 5.2 在 5.1 基礎上繼續改進和優化,添加了許多新的功能特性...';
return view('my_laravel', compact('data', 'content'));

// 在模板中(和前兩個不太一樣)
<?php echo $data['title'] ; ?>
<?php echo $data['subTitle']; ?>
<?php echo $content; ?>

其中,view() 函數的第一個參數 my_laravel 是視圖模板名,它在resources/views 視圖目錄下,模板文件后綴是 .blade.php,采用了 Blade 模板引擎。

 

三、Blade 模板引擎

1. 輸出變量

// 輸出單個變量
{{ $var }}

// 保留雙大括號,編譯為{{ var }}
@{{ var }}

// 可以輸出默認值
{{ $var or '我是默認值' }}
{{ isset($var) ? $var : '我是默認值' }}

// Blade 注釋
{{-- 這個注釋不會輸出到頁面中 --}}

// 忽略字符實體化,輸出 JS 或 HTML
{!! $var !!}
// 注: 因為 Blade 模板引擎默認對{{}}語句進行了 htmlentities 字符實體化,所以要輸出JS或HTML代碼時,應使用上述語法

  

2. 流程控制

// if 語句
@if($var == 'laravel')
    I am laravel
@elseif($var == 'yii')
    I am yii
@else
    I don’t know what I am.
@endif

// 循環
@for ($i = 0; $i < 10; $i++)
    The current value is {{ $i }}
@endfor

@foreach ($array as $v)
    <p>我是數組成員 {{$v}}</p>
@endforeach

@forelse ($users as $v)
    <li>我的名字是{{ $v->name }}</li>
    @empty
    <p>我沒有名字</p>
@endforelse

@while (true)
    <p>我一直在循環...</p>
@endwhile

// 可以嵌套
@for($i = 0; $i < 10; $i++)
    @if($i > 5)
        I am {{$i}} > 5
    @endif
@endfor

  

3. 模板布局和子視圖

@include           文件包含指令。

@extends          模板繼承指令。

@yield               切片定義指令(定義切片顯示位置)。

@section           切片提供指令(定義切片詳細內容)。

@endsection      @section 的結束標記。

@show               @section 的結束標記,提供切片內容的同時,顯示切片。

@parent             @section 的內容標記,顯示出父級模板的切片。

@include: 包含子視圖,也就是文件包含。

如果一個網站中的多個網頁均有公共部分,比如頂部導航、側欄推薦、底部版權。為了便於后期維護和修改,可以把這些網頁的公共部分摘出來作為單獨的文件,放到視圖目錄下的 common 文件夾,並分別命名為 top.balde.php、aside.blade.php 和 bottom.blade.php 。那么在我們的各個視圖模板中,可以使用 

 @include('common.top')  // 將頂部導航包含進來,其他公共部分同樣處理。

 如果需要傳遞變量,可以添加參數

 @include('common.top', ['location' => '首頁']) 

 

@extends: 模板繼承,繼承父級模板的布局。

在 @include 指令中,它是把摘出的模板部分包含進來。

而 @extends 指令, 則繼承了一個已有的主模板布局。 

現在在視圖目錄下有一個 layouts 目錄,目錄下有一個主模板 master.blade.php,布局如下:

<!DOCTYPE html>
<html>
<head>
    <title>@yield('title', '首頁')</title>
</head>
<body>
    <div class="top">頂部</div>
    @yield('main')
    <div class="aside">側欄</div>
    <div class="bottom">底部</div>
</body>
</html>

@yield('title', '首頁') 指令定義了在<title>標簽中顯示網頁標題

@yield('main') 定義了在頂、側欄之間顯示主內容。

 

那么標題和主內容在哪里呢?這就需要子模板了。

現在我們在視圖目錄下新建一個子模板 child.blade.php,內容如下:

@extends('layouts.master')

@section('title')
    關於頁
@endsection

@section('main')
    <div class="main">【關於頁】主內容</div>
@endsection

   

定義好指向 master 主模板視圖 和 child 子模板視圖的路由,瀏覽器中訪問 child 子視圖

 

我們看到,child 子模板繼承了 master 主模板的內容:頂部、側欄、底部

同時,child 子模板也顯示了自己的網頁標題 “關於頁” 和主內容 “【關於頁】主內容”

這就是 master 主模板中切片定義者 @yield 和 child 子模板中切片提供者 @section@endsection 的功勞了。

 

@yield、@section: 定義切片和提供切片。

@yield('main') 指令定義一段HTML切片,它指示了在這個位置顯示一個名為'main'的切片

@section('main')@endsection 指令提供了一段HTML切片,它為@yield('main') 定義的'mian'切片提供了詳細的內容。

那么有了切片的顯示位置,有了切片的詳細內容,就可以顯示出一個詳細的HTML切片了。

 

應該注意到了,在主模板 master 中有這么一個

@yield('title', '首頁')

它指示了 'title' 切片的默認值。就是說,如果沒有子模板繼承主模板,或者繼承了但沒有用@section('title')@endsection 指令提供 'title' 切片,它將顯示一個默認值 '首頁' 。

現在,直接訪問主模板看看

沒錯,沒有子模板用 @section('title')@endsection 來提供標題, @yield('title', '首頁') 顯示了 'title' 切片的默認值 '首頁'。

 

那么,主模板作為網站首頁的話,它的主內容呢?如果要顯示的話,難道又要寫一個子模板來繼承它,再用 @section@endsection 提供主內容?可不可以直接在主模板里寫一個類似@yield('title', '首頁') 提供的默認值呢?

當然可以,下面來重寫主模板

<!DOCTYPE html>
<html>
<head>
    <title>@yield('title', '首頁')</title>
</head>
<body>
    <div class="top">頂部</div>
    @section('main')
        <div class="main">【首頁】主內容</div>
    @show
    <div class="aside">側欄</div>
    <div class="bottom">底部</div>
</body>
</html>

@section('main')@show 可以提供 'main' 切片並顯示出來。

 

現在訪問主模板看看,首頁主內容出來了。

並且,如果有子模板繼承,並用 @section('main')@endsection 中也提供了一段'main'切片的話,這將覆 蓋 主模板中的 'main'切片,而只顯示自己定義的。類似於面向對象的重寫。

在重寫了主模板后,再訪問子模板看看

因為子模板中 @sectioin('main')@endsection 提供了'main'切片,所以覆蓋了父級中的'main'。

 

有時候可能需要子模板中重寫但不覆蓋主模板的切片內容,那么可以在子模板中使用 @parent 來顯示主模板中的切片

@extends('layouts.master')

@section('title')
    關於頁
@endsection

@section('main')
    @parent
    <div class="main">【關於頁】主內容</div>
@endsection

 

訪問子模板

顯示子模板主內容的同時,也顯示了主模板的主內容。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM