引入
假设有如下情景,我们做一个系统他的导航菜单,侧边栏,底部信息等在多个页面都会用到,因此最好的处理办法是将这些内容写成一个组件
,每个页面直接调用即可,但是如何将数据传入到组件?每个页面都有对应的控制器,那我们是不是每一次都要有在不同的控制器里面获取这些组件的数据,只要模板调用了相关组件,这样做是不是太繁琐了?
那有没有一种办法可以实现“一处定义,多处复用”?这样就不用每次在控制器获取组件的数据了。
在Laravel中,我们可以通过 View Composer
实现这个功能,我们在后台通过 View Composer
将数据绑定到指定视图即可
使用方法
1.在app\Providers\AppServiceProvider
的boot
方法进行设置
view()->composer('left',function($view){
$view->with('articles',Article::all());
})
composer('BladeName',function($view()))
composer第一个参数设置数据在那个组件模板生效
composer第二个参数设置数据传递闭包函数
上述代码表示,将Article模型所有数据通过articles
传递给left
模板
在left
组件中可以直接使用articles
变量获取数据
如:
{{-- left.blade.php--}}
<ul>
@foreach($articles as $v)
<li>{{$v->title}}</li>
@endforeach
</ul>
设置好left
组件后,在需要的界面调用left
即可
如:
<div class='main'>
<div class='top'>
顶部内容
</div>
<div class='left'>
{{-- 调用left组件--}}
@component('left')
@endcomponent
</div>
<div class='foot'>
底部内容
</div>
</div>
显示效果
当然,你还可以通过数组/通配符指定多个视图生效
view()->composer(['top','left'],function($view){
$view->with('articles',Article::all());
})
//通配符指定
view()->composer('top.*',function($view){
$view->with('articles',Article::all());
})
上述代码表示,top
和left
组件或者以top
开头的模板共用articles
变量
通过自定义类
除了使用boot
闭包方法外,还可以通过自定义类的方式为 View Composer
实现更加灵活的数据预设。
在app/Http/ViewComposer
目录下创建一个自定义 View Composer
类
<?php
namespace App\Http\ViewComposers;
use App\Article;
use Illuminate\Contracts\View\View;
class DataArticleComposer
{
private $articles;
public function __construct(Article $articles){
$this->articles = $articles;
}
public function compose(View $view){
//这里编写数据预设逻辑
$view->with('articles',$this->articles->all());
}
}
在DataArticleComposer
中构造函数注入模型类,并设置模型属性,在compose
方法中写入数据预设逻辑,完成该类的定义之后我们在app\Providers\AppServiceProvider
的boot
方法中调用DataArticleComposer
类即可
view()->composer('left',\App\Http\ViewComposers\DataArticleComposer::class);
数据跟之前显示一样,不过这种方法一般用于代码逻辑较复杂的时候使用,简洁的代码尽量使用第一种方式。
视图中注入服务
待补充…
自定义Blade指令
在Laravel中我们可以自定义Blade指令,这样做的好处是替换那些重复编写,实现同样功能的代码,提高代码可读性及复用性
如Laravel中的验证用户登录使用的指令
@auth
//用户已经登录
@endauth
@guest
//用户没有登录
@endguest
如果没有这个指令,我们就要使用判断语句编写相应逻辑,同样我们也可以自定义类似指令
如 时间格式化,如果数据库存储的是时间戳,那么数据传到模板时我们需要编写代码将时间格式化,编写同样的代码较繁琐,我们可以先将代码逻辑定义好,在使用的时候直接调用即可
要实现自定义指令我们需在app\Providers\AppServiceProvider
的boot
方法注册这个指令,通过Blade::directive
方法
Blade::directive('datatime',function($expression){
return "<?php echo ($expression)->format('Y-m-d H:i:s');?>";
})
directive
的第一个参数为指令名,第二个参数为闭包函数,实现指令逻辑
定义好后我们直接在模板中使用此指令
@datetime($time)
显示结果,成功时间格式化
注:更新完 Blade 指令逻辑后,必须删除所有的 Blade 缓存视图。缓存的 Blade 视图可以通过 Artisan 命令 view:clear 移除。
自定义If语句
Laravel中还可以自定义if语句,如自定义一个条件来检查当前应用的环境。
1.在app\Providers\AppServiceProvider
的boot
方法中定义逻辑
Blade::if('env',function($environment){
return app()->environment($environment);
});
定义好自定义条件后,就可以在模板中使用了
@env('local')
本地环境
@elseenv('test')
测试环境
@else
没有环境
@endenv