说明:本文主要讲述Laravel容器事件,并更根据容器事件做一个简单demo供加深理解容器事件。同时,作者会将开发过程中的一些截图和代码黏上去,提高阅读效率。
Container是Laravel框架的核心,Container中储存着各种各样的Service,并且每一个Service通过Service Provider注册在Container里,通过Facade模式帮我们从容器里去解析需要的Service对象。而这个过程中,容器每一次从容器中解析对象时是会触发一个事件的,可以通过resolving
方法监听到。实际上在Laravel框架中表单请求验证就用到这个好工具,通过一个表单请求类来实现表单内容验证,以免把逻辑放在控制器里弄乱控制器,具体可以看中文文档:表单请求验证。关于Container Event可以看文档:容器事件。
Container Event在表单请求中的应用
先写路由:
代码语言:javascript复制Route::post('containerevent', 'ContainerEventController@containerEvent');
Route::post('formrequest', 'ContainerEventController@formRequest');
Route::get('container', 'ContainerEventController@profile');
再建个控制器:
代码语言:javascript复制php artisan make:controller ContainerEventController
写上方法:
代码语言:javascript复制 public function containerEvent()
{
}
public function formRequest()
{
}
public function profile()
{
return view('profile');
}
写上view:
代码语言:javascript复制<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap Template</title>
<!-- 新 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">
<style>
html,body{
width: 100%;
height: 100%;
}
*{
margin: 0;
border: 0;
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-xs-12 col-md-12">
<form action="/formrequest" method="post" accept-charset="UTF-8" enctype="multipart/form-data">
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" name="name" placeholder="Name">
</div>
<div class="form-group">
<label for="age">Age</label>
<input type="text" class="form-control" id="age" name="age" placeholder="Age">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
</div>
<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
<script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script>
</script>
</body>
</html>
写个表单请求类:先输入命令生成表单请求类
代码语言:javascript复制php artisan make:request ContainerFormRequest
再给出验证规则
代码语言:javascript复制class ContainerFormRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;//改为true,这里一般用作用户验证,这里全部通过验证
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => 'required',
'age' => 'required|numeric|min:18',
];
}
}
修改ContainerEventController:
代码语言:javascript复制public function formRequest(ContainerFormRequest $containerFormRequest)
{
dd('This is a From Request Container Event. It is working!!!');
}
同时把app/Http/Kernel.php文件中AppHttpMiddlewareVerifyCsrfToken::class注销掉,否则提交表单TokenMismatchException错误。
好,输入路由(修改为你的路由):http://laravelcontainerevent.app:8888/container,则输入错误表单会返回到当前表单页面,正确提交输入表单后会打印:
说明fromRequest已经工作了,ContainerFormRequest这个对象从容器中解析的时候,会先工作authorize
和rules
方法。而控制器中只需要注入ContainerFormRequest这个对象就行了。
Demo
实现一个自定义的类,实现表单提交相同的功能。在app/Contracts文件夹中新建EventBeforeResolving.php文件:
代码语言:javascript复制namespace AppContracts;
interface EventBeforeResolving
{
public function isAdult();
}
并在一个service provider注册下:
代码语言:javascript复制//AppServiceProvider.php
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//当从容器中解析注入到控制器中前,会先调用实现EventBeforeResolving接口对象的isAdult()方法
$this->app->resolving(EventBeforeResolving::class,function($obj, $app){
$obj->isAdult();
});
}
写一个service实现这个接口:
代码语言:javascript复制//app/Services/Authorize.php
namespace AppServices;
use AppContractsEventBeforeResolving;
use IlluminateHttpRequest;
class Authorize implements EventBeforeResolving
{
private $request;
public function __construct(Request $request)
{
$this->request = $request;
}
public function isAdult()
{
$name = $this->request->input('name');
$age = $this->request->input('age');
if(empty($name) || empty($age) || ($age < 18)){
dd('Name and Age must be required. And Age must be above 18');
}
}
}
修改下ContainerEventController:
代码语言:javascript复制 public function containerEvent(Authorize $authorize)
{
dd('This is a Demo Container Event. It is working!!!');
}
同时别忘了修改下profile.blade.php文件中表单提交action='/containerevent'。
当输入错误时会提示错误信息:
Container Event就是在Service对象从容器中解析注入前触发事件,可以利用这个功能做一些有趣又好用的好东西呢,比如Laravel框架的表单请求验证就是这么做的,这样不会把验证逻辑代码放在控制器中,以免弄乱控制器。
总结:本节主要讲述Laravel的容器事件,并以Form Requet为例说明它的用途,同时以一个小demo讲述怎么一步步建立并监听容器事件。嘛,过两天还想结合Laravel的Task Scheduler任务调度新开篇章,到时见。