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

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

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

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

在每个 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

  1. View::composer(
  2. 'profile', 'App\Http\ViewComposers\ProfileComposer'
  3. );

Closure based composers

  1. View::composer('dashboard', function ($view) {
  2. //
  3. });

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

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

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

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

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

View composer 统一放到目录

app/Http/ViewComposers

下。

Laravel 内置的命令

  1. make:provider Create a new service provider class

  1. php artisan make:provider SidebarCompoerServiceProvider

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

app/Providers/SidebarCompoerServiceProvider.php

  1. namespace App\Providers;
  2. use Illuminate\Support\ServiceProvider;
  3. class SidebarCompoerServiceProvider extends ServiceProvider
  4. {
  5. /**
  6. * Bootstrap the application services.
  7. *
  8. * @return void
  9. */
  10. public function boot()
  11. {
  12. // View::composer
  13. }
  14. /**
  15. * Register the application services.
  16. *
  17. * @return void
  18. */
  19. public function register()
  20. {
  21. //
  22. }
  23. }

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

添加 service provider 到 config.php 中

参考 AppServiceProvider 的做法

App\Providers\AppServiceProvider::class,

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

  1. View::composer(
  2. ['profile', 'dashboard'],
  3. 'App\Http\ViewComposers\MyViewComposer'
  4. );

当然也可以使用星号为所有模板提供数据 (严重不推荐, 这跟之前的 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

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

代码填充如下

  1. <?php
  2. namespace App\Http\ViewComposers; // 注意修改 namespace
  3. use Illuminate\Support\ServiceProvider;
  4. use Illuminate\Support\Facades\View;
  5. use App\Models\WebExamInfo;
  6. use App\Models\Live;
  7. class SidebarComposerServiceProvider extends ServiceProvider
  8. {
  9. /**
  10. * Bootstrap the application services.
  11. *
  12. * @return void
  13. */
  14. public function boot()
  15. {
  16. View::composer('detail_sidebar', function ($view) {
  17. // 招考信息
  18. $exams = WebExamInfo::orderBy('id', 'desc')
  19. ->limit(6)
  20. ->get();
  21. // 直播信息
  22. $lives = Live::where('is_deleted', 0)
  23. ->orderBy('id', 'desc')
  24. ->limit(6)
  25. ->get();
  26. $view->with('exams', $exams)
  27. ->with('lives', $lives);
  28. });
  29. }
  30. /**
  31. * Register the application services.
  32. *
  33. * @return void
  34. */
  35. public function register()
  36. {
  37. //
  38. }
  39. }

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

  1. App\Http\ViewComposers\SidebarComposerServiceProvider::class,

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

Laravel View Composer - 当 include 一个模板时,自动获取其所需的变量的更多相关文章

  1. zTree异步生成数据时无法获取到子节点的选中状态

    最近在项目中遇到一个问题,需求如下: 根据选中不同的人员(ID)向后台发送ajax请求,通过返回的数据来生成该人员的权限访问树,该树目录最少为3级目录,在生成的时候会自动勾选上次保存过的选中状态,点击 ...

  2. VMware vSphere 服务器虚拟化之二十二桌面虚拟化之创建View Composer链接克隆的虚拟桌面池

    VMware vSphere 服务器虚拟化之二十二桌面虚拟化之创建View Composer链接克隆的虚拟桌面池 在上一节我们创建了完整克隆的自动专有桌面池,在创建过程比较缓慢,这次我们将学习创建Vi ...

  3. win7,M​i​n​d​m​a​n​a​g​e​r​2​0​1​2使用模板时弹出Runtime error R6025解决方法

    Mindjet.MindManager2012.v10.0在应用个别模板时提示"参数错误",然后自动关闭. 解决办法: 如果是win7系统,可以进入C:\Users\(用户名)\A ...

  4. iOS开发UI篇—使用picker View控件完成一个简单的选餐应用

    iOS开发UI篇—使用picker View控件完成一个简单的选餐应用 一.实现效果 说明:点击随机按钮,能够自动选取,下方数据自动刷新. 二.实现思路 1.picker view的有默认高度为162 ...

  5. php包含(include/require)文件时的作用域

    当一个php脚本被require/include时,他的变量作用域根据其上下文环境决定. 1.如果是在一个函数中require/include一个文件,则此文件中的变量作用域是这个函数的范围.也就是说 ...

  6. listview当选中某一个item时设置背景色其他的不变

    listview当选中某一个item时设置背景色其他的不变: 可以使用listview.setOnFoucsChangeListener(listener) ; /** * listview获得焦点和 ...

  7. VMware vSphere 服务器虚拟化之十八桌面虚拟化之安装View Composer服务器

                        VMware vSphere 服务器虚拟化之十八桌面虚拟化之安装View Composer服务器      View Compose服务可安装在管理虚拟机的vC ...

  8. thinkphp 使每一个模板页都包括一个header文件和一个footer文件

    在开发的过程中,常常遇到要使每一个模板页都包括一个header文件和一个footer文件.thinkPHP的模板布局为我们提供了一个叫全局配置方式可以解决问题. 1. 在配置文件里开启LAYOUT_O ...

  9. FreeMarker 语法 include 引用模板

    一.java 代码 @Test public void testFreeMarker() throws Exception { //1.创建一个模板文件 //2.创建一个Configuration对象 ...

随机推荐

  1. python 压缩文件为zip后删除原文件

    压缩.log 文件为zip后删除原文件 需要注意:本人作为小白,该脚本需要和.log在一起,后面有时间需要改正. #!/usr/local/python/bin/python #-*-coding=u ...

  2. Linux命令之ls

    ls命令 用处:列出此目录下的文件和目录 用法:直接在终端中输入ls就好了 示例: 看到了吗,文件夹和文件都显示出来了哦 可是,电脑里面有时会有一些隐藏文件,我还想看到这些隐藏文件怎么办呢?加  -a ...

  3. Study 8 —— 数据类型(列表/list)

    列表是一个数据的集合,集合内可以放任何数据类型,可对集合进行方便的增删改查操作 1. 定义列表: 方法一: L1 = [] #定义空列表 L2 = ['A', 'B', 'C']  #存3个值,索引0 ...

  4. Study 1 —— Python简介

    Python与其他语言的区别C\C++:学习成本高,学习周期长,偏系统底层,在开发硬件驱动.嵌入式.游戏引擎开发等领域有广泛的应用:JAVA:目前使用最广泛的编程语言,第一个跨平台运行的语言,在大型E ...

  5. java compareTo() 用法注意点

    转自:http://www.2cto.com/kf/201305/210466.html compareTo就是比较两个值,如果前者大于后者,返回1,等于返回0,小于返回-1,我下面给出了例子,由于比 ...

  6. 八皇后问题动态演示_Qt5实现

    //核心代码如下 //Queen--放置皇后 #include "queue.h" queue::queue() { *; ; this->board = new bool[ ...

  7. ATS metric query

    ATS metric query 参考:ATS metric query proxy.node.cache_hit_mem_ratio proxy.node.cache_hit_mem_ratio_a ...

  8. Java实现DOS中的Copy命令

    import java.io.*; import java.util.Scanner; public class fileCopy { public static void main(String [ ...

  9. 【输入法】Rime-中州韵 基本设置 附:官方定制指南

    前言 不知不觉就到了年终了,距离上次更新博客已经有一个半月,这段时间天天在加班,也没作一下新的学习计划,趁着元旦放假,写一点好玩的东西,这次要记录的是一点关于Rime相关的东西,文章本身不会长,只是说 ...

  10. VS复制文件到输出目录

    1.选中项目文件 2. 3.编译时就会自动创建目录,并复制文件