第三章 Laravel 控制器
为了替代在路由文件中以闭包形式定义的所有的请求处理逻辑, 你可能想要使用控制类来组织这些行为。控制器能将相关的请求处理逻辑组成一个单独的类。控制器被存放在 app/Http/Controllers
目录。
3.1 基础控制器:
3.1.1 定义控制器:
下面是一个基础控制器类的例子。需要注意的是,该控制器继承了 Laravel 的基类控制器。该基类控制器提供了一些便利的方法,比如 middleware
方法,该方法可以为控制器行为添加中间件:
创建控制器命令:php artisan make:controller UserController
迁移数据命令:php artisan migrate
如果报错提示:
PDOException::("SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 1000 bytes") D:\phpstudy_pro\WWW\blog\vendor\laravel\framework\src\Illuminate\Database\Connection.php:459
可以在 AppServiceProvider.php 文件(此文件在app/Providers/下)里的 boot 方法里设置一个默认值:
use Illuminate\Support\Facades\Schema;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
//
Schema::defaultStringLength(191);
}
}
加入测试数据:
进入tinker命令: php artisan tinker
填充快捷方法: factory(App\User::class,5)->create();
<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* 显示给用户的概要文件.
*
* @param int $id
* @return View
*/
public function show($id)
{
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
你可以这样定义一个指向控制器行为的路由,当一个请求与指定路由的 URI 匹配时,UserController
控制器中的 show
方法将被执行。路由参数也将会被传递给该方法。
Route::get('user/{id}', 'UserController@show');
3.1.2 控制器 & 命名空间:
需要着重指出的是,在定义控制器路由时我们不需要指定完整的控制器命名空间。因为 RouteServiceProvider
会在一个包含命名空间的路由组中加载路由文件,我们只需要指令类名中 App\Http\Controllers
命名空间之后的部分就可以了。
如果你选择将控制器放在 App\Http\Controllers
更深层次的目录中,需要使用相对于 App\Http\Controllers
作为根命名空间的指定类名。因此,如果你完整的控制器类名为 App\Http\Controllers\Photos\AdminController
,你在路由中应该采用如下的形式注册:
Route::get('foo', 'Photos\AdminController@method');
定义在路由文件中的内容实际都是在app\Providers\RouteServiceProvider.php
进行了路由文件的引入后才能进行路由的定义。
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Route;
class RouteServiceProvider extends ServiceProvider
{
/**
* This namespace is applied to your controller routes.
*
* In addition, it is set as the URL generator's root namespace.
*
* @var string
*/
#protected $namespace = 'App\Http\Controllers\Photos';
protected $namespace = 'App\Http\Controllers';
*/
public function map()
{
$this->mapWebRoutes();
//
}
/**
* Define the "web" routes for the application.
*
* These routes all receive session state, CSRF protection, etc.
*
* @return void
*/
protected function mapWebRoutes()
{
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
}
通过命令artisan所创建的控制器,通常是会继承与App\Http\Controllers\Controller
。但是实际上我们是可以不用继承与这个类。只是这样我们可能就不能够很方便的使用middleware
,validate
和dispatch
方法。
以后在业务、功能我们就可以选择拆分来使用,提取公用操作类库,在统一模块下面进行使用操作:
3.1.3 单个行为控制器:
如果你想要定义一个只处理单个行为的控制器,你可以在控制器中放置一个 __invoke
方法:
<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
class ShowProfile extends Controller
{
/**
* 显示给定用户的资料.
*
* @param int $id
* @return View
*/
public function __invoke($id)
{
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
当注册单个行为控制器的路由时,你不需要指明方法:
Route::get('user/{id}', 'ShowProfile');
你可以通过 Artisan 命令工具里的 make:controller
命令中的 --invokable
选项来生成一个可调用的控制器:
php artisan make:controller ShowProfile --invokable
3.2 控制器中间件:
Middleware 可以在路由文件中分配给控制器的路由:
Route::get('profile', 'UserController@show')->middleware('auth');
然而,在控制器的构造函数中指定中间件更为方便。使用控制器构造函数中的 middleware
方法,可以轻松地将中间件分配给控制器的操作。你甚至可以将中间件限制为控制器类上的某些方法。
class UserController extends Controller
{
/**
* 实例化一个新的控制器实例.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('log')->only('index');
$this->middleware('subscribed')->except('store');
}
}
同时,控制器还允许你使用一个闭包来注册中间件。这为不定义整个中间件类的情况下为单个控制器定义中间件提供了一种方便的方法:
$this->middleware(function ($request, $next) {
// ...
return $next($request);
});
3.3 请求:
3.3.1 接收请求:
接收请求:要通过依赖注入获取当前 HTTP 请求实例,你应该在控制器上引入 Illuminate\Http\Request
类, 传入的请求实例将会由 服务容器 自动注入。
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* 存储一个新用户。
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$name = $request->input('name');
}
}
依赖注入 & 路由参数:如果你的控制器需要从路由参数中获取数据,你应该在其他依赖项之后列入参数。举个例子,你的路由是这样定义的。
Route::put('user/{id}', 'UserController@update');
你可以通过下面的方法来定义控制器,使用 Illuminate\Http\Request
类来获取你的路由参数 id
:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* Update the specified user.
*
* @param Request $request
* @param string $id
* @return Response
*/
public function update(Request $request, $id)
{
//
}
}
通过闭包路由获取参数:你也可以在路由闭包中使用 Illuminate\Http\Request
类, 服务容器会自动的将请求参数注入到路由闭包中
use Illuminate\Http\Request;
Route::get('/', function (Request $request) {
//
});
检索请求路径:path
方法返回请求的路径信息。因此,如果接收到的请求目标是 http://domain.com/foo/bar
,则 path
方法会返回 foo/bar
:
$uri = $request->path();
is
方法验证请求的路径是否与给定的模式匹配。使用此方法时,可以将 *
字符作为通配符:
if ($request->is('admin/*')) {
//
}
检索请求URL:要获取请求的完整 url ,可以使用 url
或 fullUrl
方法。 url
方法返回不带查询条件的 url 字符串,而 fullUrl
方法包含查询字符串:
// 没有查询字符串...
$url = $request->url();
// 带查询字符串...
$url = $request->fullUrl();
检索请求方法:method
方法将会返回请求的 HTTP 动词。你也可以使用 isMethod
方法验证 HTTP 动词是否与给定的字符串匹配:
$method = $request->method();
if ($request->isMethod('post')) {
//
}
3.3.2 接收数据:
获取所有输入数据:你可以用 all 方法获取请求数据数组:
$input = $request->all();
获取一个值:使用一些简单方法,你可以从 Illuminate\Http\Request
获取所有的用户输入数据,不用担心用户使用的是那种 HTTP 动作。不管是什么 HTTP 动词,都可以使用 input
方法获取用户输入的数据:
$name = $request->input('name');
你可以给 input
方法传第二个参数。如果请求中没有呈递该参数则会返回此值:
$name = $request->input('name', 'Sally');
当有呈递数组输入的数据时,可以使用「点」 运算符访问数据:
$name = $request->input('products.0.name');
$names = $request->input('products.*.name');
你可以使用不带参数的 input
方法,它将返回一包含所有用户输入数据的数组:
$input = $request->input();
从查询字符串获取输入:
input
方法从整个请求体获取值(包含字符串), query
仅从查询字符串中获取输入值:
$name = $request->query('name');
如果请求中不存在查询的字符串,则第二个参数将作为默认值返回:
$name = $request->query('name', 'Helen');
你可以使用不带任何参数的 query
方法来获取所有查询条件的关联数组:
$query = $request->query();
获取部分输入数据:
如果需要获取输入数据的子集,可以使用 only
或 except
方法。它们接受单个 array 或者动态参数列表:
$input = $request->only(['username', 'password']);
$input = $request->only('username', 'password');
$input = $request->except(['credit_card']);
$input = $request->except('credit_card');
判断输入值是否存在:
has
方法用于判定请求中是否存在指定的值。如果请求中存在该值, has
方法返回 true
:
if ($request->has('name')) {
//
}
如果给出一个数组, has
方法将判断在请求中,指定的值是否全部存在:
if ($request->has(['name', 'email'])) {
//
}
如果想要判断一个值在请求中是否存在,并且不为空,需要使用 filled
方法:
if ($request->filled('name')) {
//
}
3.3.3 旧数据:
Laravel 允许你在两次请求之间保持数据。这个特性在有效性校验出错后重新填充表单时非常有用。不过,如果你使用 Laravel 自带 验证特性 , 不需要自己手动调用这些方法因为一些 Laravel 内置的验证功能会自动调用它们。
将输入数据传送到 Session:Illuminate\Http\Request
类的 flash 方法将把当前的输入传送到 session , 在用户向应用发出这一次请求时它们仍然可用:
$request->flash();
你也可以使用 flashOnly
或 flashExcept
方法将请求数据的子集传送给 session。这些方法常用于将密码之类的敏感数据排除在 session 保持之外:
$request->flashOnly(['username', 'email']);
$request->flashExcept('password');
传送数据并跳转:当你经常需要将输入传送至 session 并紧接着跳转至之前的页面,可以通过在跳转函数后链接调用 withInput
方法轻易地实现:
return redirect('form')->withInput();
return redirect('form')->withInput(
$request->except('password')
);
获取旧数据:若要获取上一次请求中闪存的输入,则可以使用 Request
实例的 old
方法。 old
方法会从 session 取出之前被闪存的输入数据:
$username = $request->old('username');
Laravel 也提供了全局辅助函数 old
。如果你要在 Blade 模板 中显示旧的输入,使用 old
会更加方便。如果给定字段没有旧的输入,则返回 null
:
<input type="text" name="username" value="{{ old('username') }}">
3.3.4 文件:
获取上传的文件:你可以使用 file
方法或使用动态属性从 Illuminate\Http\Request
实例中访问上传的文件。 该 file
方法返回 Illuminate\Http\UploadedFile
类的实例,该类继承了 PHP 的 SplFileInfo
类的同时也提供了各种与文件交互的方法。
$file = $request->file('photo');
$file = $request->photo;
当然你也可以使用 hasFile
方法判断请求中是否存在指定文件:
if ($request->hasFile('photo')) {
//
}
验证成功上传:除了检查上传的文件是否存在外,你也可以通过 isValid
方法验证上传的文件是否有效:
if ($request->file('photo')->isValid()) {
//
}
文件路径 & 扩展名:UploadedFile
类还包含访问文件的全路径和扩展名的方法。 extension
方法会根据文件内容判断文件的扩展名。该扩展名可能会和客户端提供的扩展名不同:
$path = $request->photo->path();
$extension = $request->photo->extension();
存储上传文件:
要存储上传的文件,先配置好 文件系统。 你可以使用 UploadedFile
的 store
方法把上传文件移动到你的某个磁盘上,该文件可能是本地文件系统中的一个位置,甚至像 Amazon S3 这样的云存储位置。
store
方法接受相对于文件系统配置的存储文件根目录的路径。这个路径不能包含文件名,因为系统会自动生成唯一的 ID 作为文件名。
store
方法还接受可选的第二个参数,用于存储文件的磁盘名称。这个方法会返回相对于磁盘根目录的文件路径:
$path = $request->photo->store('images');
$path = $request->photo->store('images', 's3');
如果你不想自动生成文件名,那么可以使用 storeAs
方法,它接受路径、文件名和磁盘名作为其参数:
$path = $request->photo->storeAs('images', 'filename.jpg');
$path = $request->photo->storeAs('images', 'filename.jpg', 's3');
3.4 响应:
3.4.1 字符串 & 数组:
所有路由和控制器处理完业务逻辑之后都会返回一个发送到用户浏览器的响应,Laravel 提供了多种不同的方式来返回响应,最基本的响应就是从路由或控制器返回一个简单的字符串,框架会自动将这个字符串转化为一个完整的 HTTP 响应:
Route::get('/', function () {
return 'Hello World';
});
除了从路由或控制器返回字符串之外,还可以返回数组。框架会自动将数组转化为一个 JSON 响应:
Route::get('/', function () {
return [1, 2, 3];
});
3.4.2 Response 对象:
通常,我们并不只是从路由动作简单返回字符串和数组,大多数情况下,都会返回一个完整的Illuminate\Http\Response
实例或 视图。
返回完整的 Response
实例允许你自定义响应的 HTTP 状态码和响应头信息。 Response
实例 继承自 Symfony\Component\HttpFoundation\Response
类, 该类提供了各种构建 HTTP 响应的方法:
Route::get('home', function () {
return response('Hello World', 200)
->header('Content-Type', 'text/plain');
});
3.4.3 添加响应头:
大部分的响应方法都是可链式调用的,使得创建响应实例的过程更具可读性。例如,你可以在响应返回给用户前使用 header
方法为其添加一系列的头信息:
return response($content)
->header('Content-Type', $type)
->header('X-Header-One', 'Header Value')
->header('X-Header-Two', 'Header Value');
或者,你可以使用 withHeaders
方法来指定要添加到响应的头信息数组:
return response($content)
->withHeaders([
'Content-Type' => $type,
'X-Header-One' => 'Header Value',
'X-Header-Two' => 'Header Value',
]);
3.4.4 重定向:
重定向响应是 Illuminate\Http\RedirectResponse
类的实例,并且包含用户需要重定向至另一个 URL 所需的头信息。Laravel 提供了几种方法用于生成 RedirectResponse
实例。其中最简单的方法是使用全局辅助函数 redirect
:
Route::get('dashboard', function () {
return redirect('home/dashboard');
});
有时候你可能希望将用户重定向到之前的位置,比如提交的表单无效时。这时你可以使用全局辅助函数 back
来执行此操作。由于这个功能利用了 会话控制,请确保调用 back
函数的路由使用 web
中间件组或所有 Session 中间件:
Route::post('user/profile', function () {
// 验证请求
return back()->withInput();
});
重定向到命名路由:
如果调用不带参数的辅助函数 redirect
时,会返回 Illuminate\Routing\Redirector
实例。这个实例允许你调用 Redirector
上的任何方法。例如为命名路由生成 RedirectResponse
,可以使用 route
方法:
return redirect()->route('login');
如果路由中有参数,可以将其作为第二个参数传递到 route
方法:
return redirect()->route('profile', ['id' => 1]);
重定向到控制器行为:
还可以生成到 controller action 的重定向。要达到这个目的,只要把 控制器 和 action 的名称传递给 action
方法。记住,不需要传递控制器的全部命名空间,Laravel 的 RouteServiceProvider
会自动将其设置为基本控制器的命名空间:
return redirect()->action('HomeController@index');
如果控制器路由需要参数,可以将其作为 action
方法的第二个参数:
return redirect()->action(
'UserController@profile', ['id' => 1]
);
重定向到外部域名:
有时候你需要重定向到应用外的域名。调用 away
方法可以达到此目的,它会创建一个不带有任何额外的 URL 编码、有效性校验和检查的 RedirectResponse
实例:
return redirect()->away('https://www.google.com');
3.4.5 其他的响应类型:
response
助手可以用于生成其它类型的响应实例。当还带参数调用 response
助手时,返回 Illuminate\Contracts\Routing\ResponseFactory
contract 的一个实现。这个契约提供了几个用于生成响应的方法:
视图响应:
如果需要把 视图 作为响应内容返回的同时,控制响应状态和头信息,就需要调用 view
方法,如果不需要传递自定义的 HTTP 状态码和自定义头信息,还可以使用全局的 view
辅助函数。
return response()
->view('hello', $data, 200)
->header('Content-Type', $type);
JSON响应:
json
自动将 Content-Type
头信息设置为 application/json
,同时使用 PHP 的 json_encode
函数将给定的数组转换为 JSON :
return response()->json([
'name' => 'Abigail',
'state' => 'CA'
]);
如果想要创建 JSONP 响应,可以结合 withCallback
方法使用 json
方法:
return response()
->json(['name' => 'Abigail', 'state' => 'CA'])
->withCallback($request->input('callback'));
文件下载:
download
方法可以用于生成强制用户浏览器下载给定路径文件的响应。 download
方法文件名作为其第二个参数,它将作为用户下载文件的文件名。最后,你可以传递 HTTP 头信息数组作为其第三个参数:
return response()->download($pathToFile);
return response()->download($pathToFile, $name, $headers);
return response()->download($pathToFile)->deleteFileAfterSend();
3.5 RESTful 风格:
定义:
REST 是 “呈现状态转移(REpresentational State Transfer)” 的缩写。或许可以这样来定义它:一种 API 的架构风格,在客户端和服务端之间通过呈现状态的转移来驱动应用状态的演进。
约束:
要让应用 RESTful 化,需要遵循以下约束。遵循了这些约束的分布式系统,就会拥有如下非功能属性:性能,伸缩性,易用性,扩展性,可见性,可移植性和可靠性。
CS 模式:
CS 模式通过分离客户端和服务器端的关注点,让客户端不再关注数据的存储问题,从而提高客户端代码的可移植性。另一方面,服务器端不再关注用户界面和用户状态,从而变得更简单,提高了伸缩性。服务器端跟客户端可以独立开发,只要它们都遵守契约。
无状态:
客户端上下文在多个请求之间是绝不会保存在服务器上的。每个请求必须包含必要的信息。无状态的服务器通过快速释放资源和简化实现提高了可伸缩性。可靠性使得从局部失败中恢复变得容易。很明显,监控系统不必通过考虑单个请求来判断请求的性质。 无状态服务器的一个缺点是降低了网络性能,因为所有需要的数据必须在每次请求中发送。
可缓存:
REST 应用程序是 web 系统,因此客户端和中间层可以缓存响应。响应必须被定义为可缓存或不可缓存的,以防客户端重复使用旧数据导致降低可靠性。如果缓存中的陈旧数据与已生成的请求的数据显著不同,则由服务器处理请求。缓存可以消除一些客户端和服务器之间的交互,这就提升了可伸缩性、效率和通过减少平均延迟达到的用户可感知的性能。
统一的接口:
使用统一的接口降低了系统复杂度和耦合度,让系统的不同部分可以独立演化。稍后会解释 URI,资源和超媒体是如何通过生成标准接口来提升用户交互可见性,降低系统复杂度,促进系统组件独立演化的。但是我们需要在效率方面做出妥协,毕竟消息是通过标准格式传输的,并不能满足所有应用对消息格式的要求。
分层的系统:
分层系统通过约束组件的行为来降低系统复杂度,组件不能越过它们的媒介层去访问其它层。通过组件的阻断来保持层间的独立性。遗留的组件可以被封装成新的层,不让旧的客户端访问。媒介层可以通过负载均衡来提升伸缩性。分层系统存在的主要不足,是它给数据处理增加了一些额外的开销,增加了延迟,对用户体验有所影响。
按需编码:
REST 允许客户端通过下载执行脚本来扩展它们的功能,简化了客户端,也提升了扩展性。但这同时也降低了可见性,所以这个约束不是必须遵循的。
元素:
REST 提供了以下几种元素来构建无状态,可伸缩的 web API。
HTTP协议:
资源
URI
超媒体
HTTP - 文本传输协议
REST 一般使用 HTTP 作为它的传输协议,因为 HTTP 提供了一些很好用的特性,如 HTTP 动词,状态码和头部信息
HTTP 动词:
HTTP 并没有定义很多动词来描述 web 服务中可能出现的行为,它只用了一个标准动词集合来处理各种相似情况,从而让 API 变得更直观。每个动词通过两种属性的组合来满足不同的场景需求。
幂等性:操作可以被重复执行,就算在失败以后。
安全性:对客户端来说操作不会产生副作用。
GET:
用来从服务器端读取状态。这个操作是安全的,所以它可以被执行很多次而不会对数据有任何影响,也就是说执行它一次跟执行十次是一样的效果。从幂等性方面来看,多次请求跟单个请求总能得到相同的结果。
POST:
一般用来在服务器端创建某种状态。这个操作不具备幂等性跟安全性,所以多次请求会在服务器端创建多个资源。因为 POST 是不幂等的, 所以不应该被用来做跟金钱有关系的操作,试想一次失败的请求如果被执行多次,那么很可能转账或者支付也被执行了多次。
PUT:
虽然它也可以被用来创建状态,但主要还是用来在服务器端更新状态的。它是幂等的,但不安全,因为它会改变服务端的状态。因为它的幂等性,PUT 可以被用来处理跟金钱有关系的操作。
DELETE:
用来在服务器端删除状态。它也是幂等非安全的,因为它会移除服务端的状态。它之所以是幂等的,是因为重复删除一个状态的结果是一样。
响应状态码:
HTTP 在请求资源的响应里提供了元数据信息,也就是状态码。它们是 web 平台之所以能用来构建分布式系统的重要因素。它们被分为以下几类:
- 1xx —— 元数据
- 2xx —— 正确的响应
- 3xx —— 重定向
- 4xx —— 客户端错误
- 5xx —— 服务端错误
头部信息:
HTTP 在消息头部里为请求响应提供了额外信息。每个头部由大小写敏感的关键字和值组成,中间用冒号隔开。头部信息被分为以下几类:
一般头部:在请求跟响应里都有,跟消息体里传输的数据没有关系。
请求头部:更多的是关于被请求资源或者客户端的信息。
响应头部:响应的额外信息。
实体头部:消息体的额外信息,比如 content-length 或 MIMI-type。
资源:
资源可以是由系统暴露出来的任何具有唯一标识的东西。资源在应用领域跟客户端之间建立起了联系。一张图片,一个表格,或者它们的集合,都被看作资源。资源通过某种呈现方式被获取或被创建 (XML,JSON 等)。 我们与之打交道的是资源的呈现形式,并不是资源本身,这个跟值传递有点像。根据之前对 REST 的定义,资源代表了在网络上传输的文档。服务器端关心资源的状态,因为它们代表了领域的状态。而客户端只是获取或者发送资源的呈现状态,从而让应用的状态发生变化。客户单关心的是应用的状态,因为这些状态的变化跟应用所要达成的目标有关系。 资源的名字都应该是名词性质的,它们代表的是系统中领域的概念,并用 URI 标识。
URIs (Uniform Resource Identifiers)
URIs 用来唯一标识资源。要访问或者操作一个资源,最起码要知道资源的地址。它们由协议 + 服务器地址 + 路径组成。
客户端不应该与资源的 URI 有太多耦合,因为服务端可能随意改变它们的值。在这一点上,超媒体更具优势。它提供了一种解耦客户端跟 URI 的方式,并在应用协议中加入新的语义。
3.6 资源控制器:
3.6.1 简介:
Laravel 的资源路由将典型的「CURD (增删改查)」路由分配给具有单行代码的控制器。例如,你希望创建一个控制器来处理保存 "照片" 应用的所有 HTTP 请求。使用 Artisan 命令 make:controller
,我们可以快速创建这样一个控制器:
php artisan make:controller PhotoController --resource
这个命令将会生成一个控制器 app/Http/Controllers/PhotoController.php
。其中包括每个可用资源操作的方法。
接下来,你可以给控制器注册一个资源路由:
Route::resource('photos', 'PhotoController');
这个单一的路由声明创建了多个路由来处理资源上的各种行为。生成的控制器为每个行为保留了方法,包括了关于处理 HTTP 动词和 URLs 的声明注释。
你可以通过将数组传参到 resource
方法中的方式来一次性的创建多个资源控制器:
Route::resources([
'photos' => 'PhotoController',
'posts' => 'PostController'
]);
3.6.2 资源控制器操作处理:
HTTP 方法 | URI | 动作 | 路由名称 |
---|---|---|---|
GET | /photos |
index | photos.index |
GET | /photos/create |
create | photos.create |
POST | /photos |
store | photos.store |
GET | /photos/{photo} |
show | photos.show |
GET | /photos/{photo}/edit |
edit | photos.edit |
PUT/PATCH | /photos/{photo} |
update | photos.update |
DELETE | /photos/{photo} |
destroy | photos.destroy |
3.6.3 制定资源模型:
如果你使用了路由模型绑定,并且想在资源控制器的方法中使用类型提示,你可以在生成控制器的时候使用 --model
选项:
php artisan make:controller PhotoController --resource --model=Photo
3.6.4 部分资源路由:
Route::resource('photos', 'PhotoController')->only([
'index', 'show'
]);
Route::resource('photos', 'PhotoController')->except([
'create', 'store', 'update', 'destroy'
]);
3.6.5 API 资源路由:
当声明用于 APIs 的资源路由时,通常需要排除显示 HTML 模板的路由(如 create
和 edit
)。为了方便起见,你可以使用 apiResource 方法自动排除这两个路由:
Route::apiResource('photos', 'PhotoController');
你可以传递一个数组给 apiResources
方法来同时注册多个 API 资源控制器:
Route::apiResources([
'photos' => 'PhotoController',
'posts' => 'PostController'
]);
要快速生成不包含 create
或 edit
方法的用于开发接口的资源控制器,请在执行 make:controller
命令时使用 --api
开关:
php artisan make:controller API/PhotoController --api
3.6.6 命名资源路由:
默认情况下,所有的资源控制器行为都有一个路由名称。你可以传入 names 数组来覆盖这些名称:
Route::resource('photos', 'PhotoController')->names([
'create' => 'photos.build'
]);
3.6.7 命名资源路由参数:
默认情况下,Route::resource
会根据资源名称的「单数」形式创建资源路由的路由参数。你可以在选项数组中传入 parameters
参数来轻松地覆盖每个资源。parameters
数组应该是资源名称和参数名称的关联数组
Route::resource('users', 'AdminUserController')->parameters([
'users' => 'admin_user'
]);
上例将会为资源的 show
路由生成如下的 URI :
/users/{admin_user}
各位同学以上就是 Laravel 控制器的全部内容,欲知更多内容,请听下章详解。