看官请绕道: Laravel 5.7 中文文档 ,此篇博客是本人复习+学习笔记。
这是我自己对于Laravel文档的一次地毯式学习,时常看文档,都能从文档中学习到或多或少的知识点.
入门指南 安装 Laravel Laravel 使用 Composer 来管理项目依赖。因此,在使用 Laravel 之前,请确保你的机器已经安装了 Composer。
1 2 3 4 5 composer global require "laravel/installer" composer create-project --prefer-dist laravel/laravel blog
配置文件
1 php artisan key:generate
这个字符串长度为 32 个字符。密钥可以在 .env
环境文件中设置。前提是你要将 .env.example
文件重命名为 .env
Web 服务器配置 Apache 如果 Laravel 附带的 .htaccess
文件不起作用,尝试下面的方法替代:
1 2 3 4 5 6 Options +FollowSymLinks -Indexes RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.php [L]
Nginx 1 2 3 location / { try_files $uri $uri / /index.php?$query_string ; }
配置信息 配置缓存 为了给你的应用程序提升速度,你应该使用 Artisan 命令 config:cache
将所有的配置文件缓存到单个文件中。 这会把你的应用程序中所有的配置选项合并成一个单一的文件,然后框架会快速加载这个文件。
1 php artisan config:cache
这个命令不应在本地开发环境下运行,因为配置选项在应用程序开发过程中是经常需要被更改的.
如果在部署过程中执行 config:cache
命令,那你应该确保只从配置文件内部调用 env
函数。 一旦配置被缓存,.env
文件将不再被加载,所有对 env
函数的调用都将返回 null
。
维护模式 当应用程序处于维护模式时,所有对应用程序的请求都显示为一个自定义视图。这样可以在更新或执行维护时轻松地「关闭」你的应用程序。
维护模式检查包含在应用程序的默认中间件栈中。如果应用程序处于维护模式,则将抛出一个状态码为 503 的 MaintenanceModeException
异常。
你还可以向 down
命令提供 message
和 retry
选项。 其中 message
选项的值可用于显示或记录自定义消息,而 retry
值可用于设置 HTTP 请求头中 Retry-After
的值:
1 php artisan down --message="Upgrading Databse" --retry=60
即使在维护模式下,也可以使用命令 allow 选项允许特定的 IP 地址或网络访问应用程序:
1 php artisan down --allow=127.0 .0.1 --allow=192.168 .0.0 /16
要关闭维护模式,请使用 up
命令:
文件夹结构
app
目录
app
目录包含应用程序的核心代码
Broadcasting
目录
Broadcasting
目录包含应用程序的所有广播频道类。 这些类可以通过使用 make:channel 命令来创建。
Console
目录
Console
目录包含了所有自定义的 Artisan
命令。这些命令可以通过 make:command
来生成。 这个目录还包含了控制台内核,控制台内核可以用来注册你的自定义 Artisan 命令和你定义的 计划任务 的地方
Events
目录
Events
目录默认是不存在的,它会在你运行 Artisan
命令 event:generate
或 make:event
时生成。Events
目录存放了 事件类。可以使用事件来提醒应用其他部分发生了特定的操作,使应用程序更加的灵活和解耦。
Exceptions
目录
Exceptions
目录包含了应用的异常处理器,也是应用抛出异常的好地方。 如果想自定义记录或者渲染异常的方式,你就要修改此目录下的 Handler
类。
Http
目录
Http
目录包含了控制器、中间件和表单请求。几乎所有的进入应用的请求的处理逻辑都被放在这里。
Jobs
目录
Jobs
目录默认是不存在的,它会在你运行 Artisan
命令 make:job
时生成。这个目录存放了应用中的 队列任务 。
Listeners
目录
Listeners
目录默认是不存在的,它会在你运行 Artisan
命令 event:generate
或 make:listener
时生成。Listeners
目录包含了用来处理 事件 的类。事件监听器接收事件实例并执行响应该事件被触发的逻辑
Mail
目录
Mail
目录默认不存在,它会在你运行 Artisan
命令 make:mail
时生成。 Mail
目录包含应用所有的邮件发送类。
Notifications
目录
Notifications
目录默认不存在,它会在你运行 Artisan
命令 make:notification
时生成。Notifications
目录包含应用发送的所有「业务性」通知,比如关于在应用中发生的事件的简单通知
Policies
目录
Policies
目录默认不存在,它会通过运行 Artisan
命令 make:policy
来创建。Policies
目录包含了应用的授权策略类。策略可以用来决定一个用户是否有权限去操作指定资源
Providers
目录
Providers
目录包含了应用的所有 服务提供者 。 服务提供者通过在服务容器中绑定服务、注册事件、以及执行其他任务来为即将到来的请求做准备来启动应用。
Rules
目录
Rules
目录默认不存在,它会在运行 Artisan
命令 make:rule
命令时被创建。Rules
目录包含应用自定义验证规则对象
bootstrap
目录
bootstrap
目录包含启动框架的 app.php
文件. 该目录还包含了一个 cache
目录,cache
目录下存放着框架生成的用来提升性能的文件,比如路由和服务缓存文件
config
目录
config
目录,顾名思义,包含应用程序所有的配置文件
database
目录
database
目录包含数据填充和迁移文件以及模型工厂类。你还可以把它作为 SQLite
数据库存放目录。
public
目录
public
目录包含了入口文件index.php
,它是进入应用程序的所有请求的入口点。 此目录还包含了一些你的资源文件(如图片、JavaScript 和 CSS)。
resources
目录
resources
目录包含了视图和未编译的资源文件(如 LESS、SASS 或 JavaScript)。此目录还包含你所有的语言文件。
routes
目录
routes
目录包含了应用的所有路由定义,Laravel
默认包含了几个路由文件:web.php
、api.php
、 console.php
和 channels.php
。
storage
目录
storage
目录包含编译后的 Blade 模板、session 会话生成的文件、缓存文件以及框架生成的其他文件。 这个目录被细分成 app
、 framework
和 logs
三个子目录
app
目录
app
目录可以用来存储应用生成的任何文件。
framework
目录
framework
目录用来存储框架生成的文件和缓存
logs
目录
logs
目录包含应用的日志文件
tests
目录
tests
目录包含自动化测试文件。在 PHPUnit
有现成的范例供你参考. 每个测试类都应该以 Test
作为后缀。 你可以使用 phpunit
或者 php vendor/bin/phpunit
命令来运行测试。
vendor
目录
vendor
目录包含你所有的 Composer
依赖包。
部署优化 优化自动加载 部署项目到生产环境时,请确保你优化了 Composer 类的自动加载映射,以便 Composer 可以快速找到正确文件为给定类加载:
1 composer install --optimize-autoloader --no-dev
除了优化自动加载之外,还应该确保项目的源代码管理库中包含了 composer.lock
文件。因为当 composer.lock
文件存在时,项目的依赖项可以被更快地安装。
优化配置加载 当你将应用部署到生产环境时,请确保在部署过程中运行 Artisan 命令:
1 php artisan config:cache
这个命令可以将所有 Laravel 的配置文件合并到单个文件中缓存,此举能大大减少框架在加载配置值时必须执行的系统文件的数量。
优化路由加载 如果你构建的是具有许多路由的大型应用程序,那你应该在部署过程中运行 Artisan 命令 route:cache :
核心架构 请求周期 第一件事
Laravel 应用的所有请求入口都是 public/index.php
文件。而所有的请求都是经由你的 Web 服务器(Apache/Nginx
)通过配置引导到这个文件。index.php
文件代码并不多,但是,这里是加载框架其它部分的起点。
index.php
文件加载 Composer
生成的自动加载设置,然后从 bootstrap/app.php
脚本中检索 Laravel 应用程序的实例
Laravel 本身采取的第一个动作是创建一个应用程序
/ 服务容器
。
HTTP / Console内核 接下来, 根据进入应用程序的请求类型来将传入的请求发送到 HTTP 内核或控制台内核。而这两个内核是用来作为所有请求都要通过的中心位置。 现在,我们先看看位于 app/Http/Kernel.php
中的 HTTP 内核。
HTTP 内核继承了 Illuminate\Foundation\Http\Kernel
类,该类定义了一个 bootstrappers 数组。 这个数组中的类在请求被执行前运行,这些 bootstrappers
配置了错误处理, 日志, 检测应用环境,以及其它在请求被处理前需要执行的任务。
HTTP 内核还定义了所有请求被应用程序处理之前必须经过的 HTTP 中间件 ,这些中间件处理 HTTP 会话 读写、判断应用是否处于维护模式、 验证 CSRF 令牌 等等。
HTTP 内核的 handle
方法签名相当简单:获取一个 Request
,返回一个 Response
。以把该内核想象作一个代表整个应用的大黑盒子,输入 HTTP 请求,返回 HTTP 响应。
服务提供者 内核启动操作中最重要的便是你应用的 服务提供者 了。所有应用下的服务提供者均配置到了 config/app.php
配置文件中的 providers
数组中。 第一步,所有服务提供者的 register
方法会被调用,然后一旦所有服务提供者均注册后, boot 方法才被调用。
请求调度 一旦启动且所有服务提供者被注册,Request
会被递送给路由。路由将会调度请求,交给绑定的路由或控制器,也当然包括路由绑定的中间件。
服务容器 绑定 绑定基础 几乎所有的服务容器绑定都是在 服务提供器, 所以文档中大多数例子都是使用了在服务提供器中绑定的容器。
简单绑定 在服务提供器中,你总是可以通过 $this->app
属性访问容器。我们可以通过容器的 bind
方法注册绑定,bind
方法的第一个参数为要绑定的类/接口名,第二个参数是一个返回类实例的 Closure
:
1 2 3 $this ->app->bind ('HelpSpot\API' , function ($app ) { return new HelpSpot \API ($app ->make ('HttpClient' )); });
绑定一个单例 singleton
方法将类或接口绑定到只解析一次的容器中。一旦单例绑定被解析,相同的对象实例会在随后的调用中返回到容器中:
1 2 3 $this ->app->singleton ('HelpSpot\API' , function ($app ) { return new HelpSpot \API ($app ->make ('HttpClient' )); });
绑定实例 你也可以使用 instance
方法将现有对象实例绑定到容器中。给定的实例会始终在随后的调用中返回到容器中:
1 2 3 $api = new HelpSpot \API (new HttpClient );$this ->app->instance ('HelpSpot\API' , $api );
绑定基本值 当你有一个类不仅需要接受一个注入类,还需要注入一个基本值(比如整数)。你可以使用上下文绑定来轻松注入你的类需要的任何值
1 2 3 $this ->app->when ('App\Http\Controllers\UserController' ) ->needs ('$variableName' ) ->give ($value );
绑定接口到实现 服务容器有一个很强大的功能,就是支持绑定接口到给定的实现
例如,如果我们有个 EventPusher
接口 和一个 RedisEventPusher
实现。一旦我们写完了 EventPusher
接口的 RedisEventPusher
实现,我们就可以在服务容器中注册它,像这样:
1 2 3 4 $this ->app->bind ( 'App\Contracts\EventPusher' , 'App\Services\RedisEventPusher' );
这么做相当于告诉容器:当一个类需要实现 EventPusher
时,应该注入 RedisEventPusher
。 现在我们就可以在构造函数或者任何其他通过服务容器注入依赖项的地方使用类型提示注入 EventPusher
接口:
1 2 3 4 5 6 7 8 9 10 11 12 use App \Contracts \EventPusher ;public function __construct (EventPusher $pusher ) { $this ->pusher = $pusher ; }
上下文绑定 有时你可能有两个类使用了相同的接口,但你希望各自注入不同的实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 use Illuminate \Support \Facades \Storage ;use App \Http \Controllers \PhotoController ;use App \Http \Controllers \VideoController ;use Illuminate \Contracts \Filesystem \Filesystem ;$this ->app->when (PhotoController ::class ) ->needs (Filesystem ::class ) ->give (function () { return Storage ::disk ('local' ); }); $this ->app->when (VideoController ::class ) ->needs (Filesystem ::class ) ->give (function () { return Storage ::disk ('s3' ); });
扩展绑定 extend
方法可以修改已解析的服务。例如,当一个服务被解析后,你可以添加额外的代码去修饰或配置这个服务。extend
方法接受一个闭包,该闭包唯一参数就是这个服务,并返回修改过的服务:
1 2 3 $this ->app->extend (Service ::class , function($service ) { return new DecoratedService ($service ); });
解析实例 make
方法你可以使用 make
方法从容器中解析出类实例。make
方法接受一个你想要解析的类名或接口名:
1 $api = $this ->app->make ('HelpSpot\API' );
如果你的代码处于无法访问 $app 变量的位置,则可用全局辅助函数 resolve 来解析:
1 $api = resolve ('HelpSpot\API' );
如果你的类依赖不能通过容器来解析,你可以通过将它们作为关联数组传递到 makeWith
方法来注入它们:
1 $api = $this ->app->makeWith ('HelpSpot\API' , ['id' => 1 ]);
自动注入 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <?php namespace App \Http \Controllers ;use App \Users \Repository as UserRepository ;class UserController extends Controller { protected $users ; public function __construct (UserRepository $users ) { $this ->users = $users ; } public function show ($id ) { } }
容器事件 服务容器每次解析对象时会触发一个事件,你可以使用 resolving
方法监听这个事件:
1 2 3 4 5 6 7 $this ->app->resolving (function ($object , $app ) { }); $this ->app->resolving (HelpSpot\API::class , function ($api , $app ) { });
基础功能 路由 这里拿Lumen的路由组展示,因为我一般用Lumen做接口开发.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?php $app ->group ([ 'prefix' => 'test' , // 路由前缀 'namespace' => 'Test' , // 命名空间 'middleware' => [ // 中间件 'TestMiddleware1' , 'TestMiddleware2' ], ], function () use ($app ) { $app ->get ('/', function () { return response ()->json ([ 'error ' => '403' ], 403); }); $app ->get ($uri , $callback ); $app ->post ($uri , $callback ); $app ->put ($uri , $callback ); $app ->patch ($uri , $callback ); $app ->delete ($uri , $callback ); $app ->options ($uri , $callback ); });
中间件 定义中间件 通过运行 make:middleware
Artisan 命令来创建新的中间件:
1 php artisan make:middleware CheckAge
该命令会在 app/Http/Middleware
目录下创建一个新的CheckAge
类,在这个中间件中,我们仅允许 age
参数大于 200
的请求对此路由进行访问,否则,将重定向到 home
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?php namespace App \Http \Middleware ;use Closure ;class CheckAge { public function handle ($request , Closure $next ) { if ($request ->age <= 200 ) { return redirect ('home' ); } return $next ($request ); } }
注册中间件 全局中间件 如果你希望中间件在应用处理每个 HTTP
请求期间运行。只需要在 app/Http/Kernel.php
中的 $middleware
属性中列出这个中间件。
为路由分配中间件 假设你想为指定的路由分配中间件,首先应该在 app/Http/Kernel.php
文件内为该中间件分配一个键。
1 2 3 4 5 6 7 8 9 10 11 12 13 protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate ::class , 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth ::class , 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings ::class , 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders ::class , 'can' => \Illuminate\Auth\Middleware\Authorize ::class , 'guest' => \App\Http\Middleware\RedirectIfAuthenticated ::class , 'signed' => \Illuminate\Routing\Middleware\ValidateSignature ::class , 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests ::class , 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified ::class , ];
一旦在 HTTP 内核中定义好了中间件,就可以通过 middleware 方法将为路由分配中间件:
1 2 3 4 5 6 7 8 Route ::get ('admin/profile' , function () { })->middleware ('auth' ); Route ::get ('/' , function () { })->middleware ('first' , 'second' );
分配中间件时,你还可以传递完整的类名
1 2 3 4 5 use App \Http \Middleware \CheckAge ;Route ::get ('admin/profile' , function () { })->middleware (CheckAge ::class );
Terminable
中间件有时中间件可能需要在 HTTP 响应构建完毕之后处理一些工作。比如,Laravel
内置的「session」
中间件会在响应构建完毕之后将会话数据写入存储器中。 如果你在中间件中定义了一个 terminate
方法,则会在响应构建完毕后,准备发往浏览器之前自动调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?php namespace Illuminate \Session \Middleware ;use Closure ;class StartSession { public function handle ($request , Closure $next ) { return $next ($request ); } public function terminate ($request , $response ) { } }
控制器 资源控制器 Laravel 资源路由将典型的「CRUD」路由分配给具有单行代码的控制器。比如,你希望创建一个控制器来处理应用保存的「照片」的所有 HTTP 请求。使用 Artisan 命令 make:controller
,我们可以快速创建这样一个控制器:
1 php artisan make:controller PhotoController --resouce
这个命令会生成一个控制器 app/Http/Controllers/PhotoController.php
。 其中包含了每个可用资源操作的方法。 接下来,你可以给控制器注册一个资源路由:
1 Route ::resource ('photos' , PhotoController');
依赖注入 & 控制器 构造函数注入 1 2 3 4 public function __construct (UserRepository $users ) { $this ->users = $users ; }
方法注入 1 2 3 4 5 6 7 8 use Illuminate \Http \Request ;public function store (Request $request ) { $name = $request ->name; }
路由缓存 如果你的应用只使用了基于控制器的路由,那么你应该利用路由缓存。 使用路由缓存将极大地减少注册所有应用路由所需的时间。
你可以使用 route:clear
命令清除路由缓存:
请求 获取请求 1 2 3 4 5 6 7 8 use Illuminate \Http \Request ;public function store (Request $request ) { $name = $request ->input ('name' ); }
通过路由闭包获取请求 1 2 3 4 5 use Illuminate \Http \Request ;Route ::get ('/' , function (Request $request ) { });
获取输入 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 $input = $request ->all ();$name = $request ->input ('name' );$name = $request ->input ('name' , 'Sally' );$name = $request ->query ('name' );$name = $request ->query ('name' , 'Helen' );$name = $request ->name;$name = $request ->input ('user.name' );$input = $request ->only (['username' , 'password' ]);$input = $request ->only ('username' , 'password' );$input = $request ->except (['credit_card' ]);$input = $request ->except ('credit_card' );
旧输入 1 2 3 4 5 6 7 8 9 10 11 12 13 $request ->flash ();$request ->flashOnly (['username' , 'email' ]);$request ->flashExcept ('password' );return redirect ('form' )->withInput ();return redirect ('form' )->withInput ( $request ->except ('password' ) ); $username = $request ->old ('username' );
文件 获取上传文件 1 2 3 4 5 6 7 $file = $request ->file ('photo' );$file = $request ->photo;if ($request ->hasFile ('photo' )) { }
验证成功上传 1 2 3 if ($request ->file ('photo' )->isValid ()) { }
文件路径 & 扩展名 1 2 $path = $request ->photo->path ();$extension = $request ->photo->extension ();
响应 创建响应 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 Route ::get ('/' , function () { return 'Hello World' ; }); Route ::get ('/' , function () { return [1 , 2 , 3 ]; }); Route ::get ('home' , function () { return response ('Hello World' , 200 ) ->header ('Content-Type' , 'text/plain' ); }); return response ($content ) ->header ('Content-Type' , $type ) ->header ('X-Header-One' , 'Header Value' ) ->header ('X-Header-Two' , 'Header Value' ); return response ($content ) ->withHeaders ([ 'Content-Type' => $type , 'X-Header-One' => 'Header Value' , 'X-Header-Two' => 'Header Value' , ]); return response ($content ) ->header ('Content-Type' , $type ) ->cookie ('name' , 'value' , $minutes ); return redirect ()->route ('login' );return redirect ()->route ('profile' , ['id' => 1 ]); return redirect ()->action ('HomeController@index' ); return redirect ()->away ('https://www.google.com' );return redirect ('dashboard' )->with ('status' , 'Profile updated!' );
视图响应 1 2 3 return response () ->view ('hello' , $data , 200 ) ->header ('Content-Type' , $type );
JSON 响应 1 2 3 4 5 6 7 8 9 return response ()->json ([ 'name' => 'Abigail' , 'state' => 'CA' ]); return response () ->json (['name' => 'Abigail' , 'state' => 'CA' ]) ->withCallback ($request ->input ('callback' ));
文件下载 download
方法可以用来生成强制用户浏览器下载指定路径文件的响应。download
方法的第二个参数接受一个文件名,它将作为用户下载的时所看见的文件名。 最后,你可以传递一个 HTTP 响应头数组作为该方法的第三个参数:
1 2 3 return response ()->download ($pathToFile );return response ()->download ($pathToFile , $name , $headers );return response ()->download ($pathToFile )->deleteFileAfterSend (true );
流式下载 有时,你可能希望将给定操作的字符串响应转换为可下载的响应,而无需将操作的内容写入磁盘。 你可以在这个场景中使用 streamDownload
方法。 此方法接受回调,文件名和可选的标题数组作为其参数:
1 2 3 4 5 return response ()->streamDownload (function () { echo GitHub ::api ('repo' ) ->contents () ->readme ('laravel' , 'laravel' )['contents' ]; }, 'laravel-readme.md' );
File 响应 file
方法可以直接在用户浏览器中显示文件(不是发起下载),例如图像或者 PDF
。此方法接受文件的路径作为其第一个参数和头信息数组作为其第二个参数:
1 2 return response ()->file ($pathToFile );return response ()->file ($pathToFile , $headers );
响应宏 如果要定义可以在各种路由和控制器中重复使用的自定义响应,可以在 Response
Facade 上使用 macro
方法。例如,你可以在 服务提供器 的 boot
方法中这样写:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?php namespace App \Providers ;use Illuminate \Support \ServiceProvider ;use Illuminate \Support \Facades \Response ;class ResponseMacroServiceProvider extends ServiceProvider { public function boot ( ) { Response ::macro ('caps' , function ($value ) { return Response ::make (strtoupper ($value )); }); } }
macro
函数接受一个名称作为其第一个参数,闭包作为第二个参数。当宏名称从 ResponseFactory
实现或者辅助函数 response
调用时,其闭包函数才会被执行:
1 return response ()->caps ('foo' );
Session 配置 Session driver
的配置预设了每个请求存储 Session 数据的位置。Laravel 自带了几个不错而且开箱即用的驱动:
file
- 将 Session 存储在 storage/framework/sessions
中。
cookie
- Sessions 被存储在安全加密的 cookie 中。
database
- Sessions 被存储在关系型数据库中。
memcached
/ redis
- Sessions 被存储在基于高速缓存的存储系统中。
array
- Sessions 存储在 PHP 数组中,但不会被持久化。
使用Session 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 $value = $request ->session ()->get ('key' );$value = session ('key' )$value = session ('key' , 'default' );session (['key' => 'value' ]);$data = $request ->session ()->all ();if ($request ->session ()->has ('users' )) { } $value = $request ->session ()->pull ('key' , 'default' );$request ->session ()->flash ('status' , 'Task was successful!' );$request ->session ()->forget ('key' );$request ->session ()->flush ();$request ->session ()->regenerate ();
表单验证 编写验证器逻辑 。为此,我们将使用 Illuminate\Http\Request
对象提供的 validate
方法 。 如果验证通过,代码就可以正常的运行。如果验证失败,则会抛出异常,并自动将对应的错误响应返回给用户。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public function store (Request $request ) { $validatedData = $request ->validate ([ 'title' => 'required|unique:posts|max:255' , 'body' => 'required' , ]); } $request ->validate ([ 'title' => 'bail|required|unique:posts|max:255' , 'body' => 'required' , ]);
验证表单请求 创建表单请求验证 1 php artisan make:request StoreBlogPost
新生成的类保存在 app/Http/Requests
目录下。如果这个目录不存在,运行 make:request
命令时它会被创建出来。让我们添加一些验证规则到 rules
方法中:
1 2 3 4 5 6 7 8 9 10 11 12 public function rules ( ) { return [ 'title' => 'required|unique:posts|max:255' , 'body' => 'required' , ]; }
你可以向 rules
方法传入所需的任何依赖项。他们会自动被 Laravel 提供的 服务容器 自动解析。
1 2 3 4 5 6 7 8 9 10 11 12 13 public function store (StoreBlogPost $request ) { $validated = $request ->validated (); }
如果验证失败,就会生成一个让用户返回到先前的位置的重定向响应。这些错误也会被闪存到 session 中,以便这些错误都可以在页面中显示出来。如果传入的请求是 AJAX
,会向用户返回具有 422
状态代码和验证错误信息的 JSON 数据的 HTTP 响应。
添加表单请求后钩子 如果你想在表单请求「之后」添加钩子,可以使用 withValidator
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public function withValidator ($validator ) { $validator ->after (function ($validator ) { if ($this ->somethingElseIsInvalid ()) { $validator ->errors ()->add ('field' , 'Something is wrong with this field!' ); } }); }
表单请求授权验证 表单请求类内也包含了 authorize
方法。在这个方法中,你可以检查经过身份验证的用户确定其是否具有更新给定资源的权限。比方说,你可以判断用户是否拥有更新文章评论的权限:
1 2 3 4 5 6 7 8 9 10 11 public function authorize ( ) { $comment = Comment ::find ($this ->route ('comment' )); return $comment && $this ->user ()->can ('update' , $comment ); }
如果 authorize
方法返回 false
,则会自动返回一个包含 403
状态码的 HTTP
响应,也不会运行控制器的方法。
如果你打算在应用程序的其它部分处理授权逻辑,只需从 authorize
方法返回 true
:
1 2 3 4 5 6 7 8 9 public function authorize ( ) { return true ; }
自定义错误消息 1 2 3 4 5 6 7 8 9 10 11 12 public function messages ( ) { return [ 'title.required' => 'A title is required' , 'body.required' => 'A message is required' , ]; }
手动创建验证器 如果你不想在请求上使用 validate
方法,你可以通过 Validator
facade 手动创建一个验证器示例。 用 Validator
facade 上的 make
方法创建一个验证器示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <?php namespace App \Http \Controllers ;use Validator ;use Illuminate \Http \Request ;use App \Http \Controllers \Controller ;class PostController extends Controller { public function store (Request $request ) { $validator = Validator ::make ($request ->all (), [ 'title' => 'required|unique:posts|max:255' , 'body' => 'required' , ]); if ($validator ->fails ()) { return redirect ('post/create' ) ->withErrors ($validator ) ->withInput (); } } }
错误 Report
辅助函数有时你可能需要报告异常,但又不希望终止当前请求的处理。report
辅助函数允许你使用异常处理器的 report
方法在不显示错误页面的情况下快速报告异常:
1 2 3 4 5 6 7 8 9 10 public function isValid ($value ) { try { } catch (Exception $e ) { report ($e ); return false ; } }
Render
方法1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public function render ($request , Exception $exception ) { if ($exception instanceof CustomException) { return response ()->view ('errors.custom' , [], 500 ); } return parent ::render ($request , $exception ); }
Reportable
& Renderable
异常1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <?php namespace App \Exceptions ;use Exception ;class RenderException extends Exception { public function report ( ) { } public function render ($request ) { return response (...); } }
HTTP
异常1 2 abort (404 );abort (403 , 'Unauthorized action.' );
日志 记录日志消息 1 2 3 4 5 6 7 8 9 10 use Illuminate \Support \Facades \Log ;Log ::emergency ($message );Log ::alert ($message );Log ::critical ($message );Log ::error ($message );Log ::warning ($message );Log ::notice ($message );Log ::info ($message );Log ::debug ($message );
记录日志到指定通道 你可以使用 Log
Facade 中的 channel
方法,将日志记录到应用配置中存在的任何渠道:
1 Log ::channel ('slack' )->info ('Something happened!' );
如果你想按需创建多个渠道的日志堆栈,你可以使用 stack
方法:
1 Log ::stack (['single' , 'slack' ])->info ('Something happened!' );
安全相关 综合话题 数据库 Eloquent ORM 测试相关 官方扩展包