zoukankan      html  css  js  c++  java
  • Laravel 5.2 三、中间件、视图与 Blade 模板引擎

    一、中间件

    Laravel 的 HTTP 中间件提供了对路由的一层过滤和保护。下面模拟一下用中间件验证后台登录。

    1. 创建中间件

    cmd 窗口进入项目目录,使用 artisan 命令创建

    php artisan make:middleware AdminLoginVerify

    这将在 app/Http/Middleware 目录创建中间件 AdminLoginVerify

    在 AdminLoginVerify 类的 handle()方法中添加验证逻辑:

    <?php
    namespace AppHttpMiddleware;
    
    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' => AppHttpMiddlewareAuthenticate::class,
            'auth.basic' => IlluminateAuthMiddlewareAuthenticateWithBasicAuth::class,
            'can' => IlluminateFoundationHttpMiddlewareAuthorize::class,
            'guest' => AppHttpMiddlewareRedirectIfAuthenticated::class,
            'throttle' => IlluminateRoutingMiddlewareThrottleRequests::class,
             // 自定义中间件
            'adminLoginVerify' => AppHttpMiddlewareAdminLoginVerify::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', 'AdminIndexController@login');
    });

    这是后台Admin 目录下 Index 控制器的代码:

    <?php
    
    namespace AppHttpControllersAdmin;
    
    use AppHttpControllersController;
    
    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

    访问子模板

    显示子模板主内容的同时,也显示了主模板的主内容。

  • 相关阅读:
    Nodejs中的流
    Openstack Havana的两个排错过程
    Mongoose入门
    Promise
    CSS3中的动画
    MySql学习笔记(一)--安装配置
    应用Dubbo框架打造仿猫眼项目(二) 影片模块开发
    应用Dubbo框架打造仿猫眼项目(一) 用户模块开发
    4种事务的隔离级别
    JAVA面试题解惑系列(一)——类的初始化顺序
  • 原文地址:https://www.cnblogs.com/mingc/p/6767895.html
Copyright © 2011-2022 走看看