zoukankan      html  css  js  c++  java
  • Laravel View Composer

    网站中,许多页面的侧边栏是相同的。例如:

    分类列表页,与文章详情页的侧边栏都包含

    • 最新文章
    • 最新评论
    • 统计计数

    这些相同的侧边栏数据也是动态的,并不是固定的。

    在每个 controller 里都写一遍数据读取逻辑,并赋值给模板,这样做有几个弊端

    • 重复编码量不小。即使提取成函数,也要手动将变量传递给模板,controller 中无法专注于业务逻辑
    • 不利于模块化

    简单粗暴的做法 - 全局 view share

    之前,我用了一种简单粗暴的解决方案:

    在 app/Providers/AppServiceProvider.php 里全局共享模板变量,即,View::share。

    但是,这种做法的弊端是

    • 及时某些页面不需要这些变量,也会浪费时间去获取一遍
    • 代码越来越臃肿

    View Composer - 当 include 一个 view 时,自动获取其所需的变量

    Laravel 的 View Composer 很好的解决了这个问题。

    官方文档: https://laravel.com/docs/5.5/views#view-composers

    View composer 实际上是一个回调,当需要渲染一个指定 blade 模板时,被自动调用。

    View Composer 需要在 service provider 中进行注册。即,新建一个 Service Provider, 然后加入到 config/app.php 中,方便 Laravel 启动时自动载入。

    这个 view composer 可以偷懒地写在 AppServiceProvider.php 中,但是,带来的问题就是代码乱的一塌糊涂。还是放到独立的文件中比较好。

    class based composers VS Closure based composers

    class based composers

    View::composer(
    'profile', 'AppHttpViewComposersProfileComposer'
    );
    

    Closure based composers

    View::composer('dashboard', function ($view) {
    //
    });
    

    我更倾向于使用 Closure based composers,这样做的好处有

    • 省去新建一个 composer 文件。因为如果没有复用、没有解耦的需求,新建一个代码文件是件我无法理解的事情
    • 逻辑一目了然,不需要再切到另外一个文件查看

    如果通过 $view->with 给一个模板传递多个变量

    // 一个变量
    $view->with('count', 1);
    
    // 多个变量
    $view->with('count', 1)
    ->with(‘site’, ‘sunzhongwei.com’);
    

    如何通过 laravel 命令创建 View Composer 文件

    View composer 统一放到目录

    app/Http/ViewComposers

    下。

    Laravel 内置的命令

    make:provider Create a new service provider class
    

    php artisan make:provider SidebarCompoerServiceProvider
    

    为何用这么长的名字?因为可以在 provider 列表里一目了然。

    app/Providers/SidebarCompoerServiceProvider.php

    namespace AppProviders;
    
    use IlluminateSupportServiceProvider;
    
    class SidebarCompoerServiceProvider extends ServiceProvider
    {
        /**
         * Bootstrap the application services.
         *
         * @return void
         */
        public function boot()
        {
            // View::composer
        }
    
        /**
         * Register the application services.
         *
         * @return void
         */
        public function register()
        {
            //
        }
    }
    

    将该文件从 app/Providers 移动到 app/Http/ViewComposers 目录下。

    添加 service provider 到 config.php 中

    参考 AppServiceProvider 的做法

    AppProvidersAppServiceProvider::class,

    一个 View Composer 给多个 blade 模板提供数据

    View::composer(
        ['profile', 'dashboard'],
        'AppHttpViewComposersMyViewComposer'
    );
    

    当然也可以使用星号为所有模板提供数据 (严重不推荐, 这跟之前的 app service provider 中的做法没有本质区别)

    Laravel Service Provider 是什么?

    https://oomusou.io/laravel/laravel-service-provider/

    我发现很难理解 Laravel Service Provider 的概念。

    先从最常见的使用场景来看:

    我们安装一个新的 Laravel 包,总是先 composer install xxx,然后修改 config/app.php 文件,在 providers 里加入 XXX::class 。

    疑问来了,composer install 之后为何还要手动配置 provider.

    因为,composer install 只是将三方包的代码安装到 vendor 目录下。

    但是,Laravel 并不知道这个三方包的存在,如果想让 laravel 启动时自动加载这个三方包,就需要在 config/app.php 的 providers 中加入这个包。

    所以,service provider 存在的意义就是方便管理哪些模块应该在 laravel 启动时自动载入的了?

    Register 和 Boot 的使用,我还是看不懂?

    一个完整的例子

    创建 View Composer Service Provider

    php artisan make:provider SidebarCompoerServiceProvider
    
    mkdir app/Http/ViewComposers
    
    mv app/Providers/SidebarComposerServiceProvider.php app/Http/ViewComposers/
    

    代码填充如下

    <?php
    
    namespace AppHttpViewComposers;   // 注意修改 namespace
    
    use IlluminateSupportServiceProvider;
    use IlluminateSupportFacadesView;
    use AppModelsWebExamInfo;
    use AppModelsLive;
    
    class SidebarComposerServiceProvider extends ServiceProvider
    {
        /**
         * Bootstrap the application services.
         *
         * @return void
         */
        public function boot()
        {
            View::composer('detail_sidebar', function ($view) {
                // 招考信息
                $exams = WebExamInfo::orderBy('id', 'desc')
                    ->limit(6)
                    ->get();
    
                // 直播信息
                $lives = Live::where('is_deleted', 0)
                    ->orderBy('id', 'desc')
                    ->limit(6)
                    ->get();
    
                $view->with('exams', $exams)
                     ->with('lives', $lives);
            });
        }
    
        /**
         * Register the application services.
         *
         * @return void
         */
        public function register()
        {
            //
        }
    }
    

    最后在 config/app.php 的 providers 中添加

    AppHttpViewComposersSidebarComposerServiceProvider::class,
    

    对应的修改 blade 渲染逻辑即可。

  • 相关阅读:
    代码操作
    购物车
    利息计算器
    生成海报
    知识库
    JavaScript处理字符串--参照W3C
    C#输入排序-冒泡
    enum举例
    C# 表达式计算器----数据结构
    C# 测试单词的完美度
  • 原文地址:https://www.cnblogs.com/sgm4231/p/10194336.html
Copyright © 2011-2022 走看看