HTTP层 —— 控制器

1、简介

将所有的请求处理逻辑都放在单个 routes.php 中显然是不合理的,你也许还希望使用控制器类组织管理这些行为。控制器可以将相关的 HTTP 请求封装到一个类中进行处理。通常控制器存放在 app/Http/Controllers 目录中。

2、基本控制器
定义控制器

下面是一个基本控制器类的例子。所有的 Laravel 控制器应该继承自 Laravel 自带的控制器基类 Controller,控制器基类提供了一些很方便的方法如 middleware ,用于添加中间件到控制器动作:

<?php

namespace App\Http\Controllers;

use App\User;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * 为指定用户显示详情
     *
     * @param int $id
     * @return Response
     */
    public function showProfile($id)
    {
        return view(‘user.profile‘, [‘user‘ => User::findOrFail($id)]);
    }
}

我们可以像这样定义指向该控制器动作的路由

Route::get(‘user/{id}‘, ‘[email protected]‘);

现在,如果一个请求匹配上面的路由 URI,UserControllershowProfile 方法就会被执行。当然,路由参数也会被传递给这个方法。

注:控制器并不是一定要继承自基类,不过,那样的话就不能使用那些便利的方法了,比如middlewarevalidatedispatch 等。

控制器 & 命名空间

你应该注意到我们在定义控制器路由的时候没有指定完整的控制器命名空间,而只是定义了 App\Http\Controllers 之后的部分。默认情况下,RouteServiceProvider 将会在一个路由群组中载入 routes.php 文件,并且该路由群组指定定了群组中路由控制器所在的命名空间。

如果你在 App\Http\Controllers 目录下选择使用 PHP 命名空间嵌套或组织控制器,只需要使用相对于App\Http\Controllers 命名空间的指定类名即可。因此,如果你的完整控制器类是App\Http\Controllers\Photos\AdminController,你可以像这样注册路由:

Route::get(‘foo‘, ‘Photos\[email protected]‘);
单动作控制器

如果你想要定义一个只处理一个动作的控制器,可以在这个控制器中定义 __invoke 方法:

<?php

namespace App\Http\Controllers;

use App\User;
use App\Http\Controllers\Controller;

class ShowProfile extends Controller
{
    /**
     * Show the profile for the given user.
     *
     * @param  int  $id
     * @return Response
     */
    public function __invoke($id)
    {
        return view(‘user.profile‘, [‘user‘ => User::findOrFail($id)]);
    }
}

当你为这个单动作控制器注册路由的时候,不需要指定方法:

Route::get(‘user/{id}‘, ‘ShowProfile‘);
3、控制器中间件

中间件可以像这样分配给控制器路由:

Route::get(‘profile‘, ‘[email protected]‘)->middleware(‘auth‘);

但是,将中间件放在控制器构造函数中更方便,在控制器的构造函数中使用 middleware 方法你可以很轻松的分配中间件给该控制器。你甚至可以限定该中间件应用到该控制器类的指定方法:

class UserController extends Controller
{
    /**
     * 实例化一个新的 UserController 实例
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware(‘auth‘);
        $this->middleware(‘log‘)->only(‘index‘);
        $this->middleware(‘subscribed‘)->except(‘store‘);
    }
}

注:你可以将中间件分配给多个控制器动作,不过,这意味着你的控制器会变得越来越臃肿,这种情况下,需要考虑将控制器分割成更多、更小的控制器。

4、资源控制器

Laravel 的资源控制器使得构建围绕资源的 RESTful 控制器变得毫无痛苦,例如,你可能想要在应用中创建一个控制器,用于处理关于图片存储的 HTTP 请求,使用 Artisan 命令 make:controller,我们可以快速创建这样的控制器:

php artisan make:controller PhotoController --resource

该 Artisan 命令将会生成一个控制器文件 app/Http/Controllers/PhotoController.php,这个控制器包含了每一个资源操作对应的方法。

接下来,可以为该控制器注册一个资源路由:

Route::resource(‘photos‘, ‘PhotoController‘);

这个路由声明包含了处理图片资源 RESTful 动作的多个路由,相应地,Artisan 生成的控制器也已经为这些动作设置了对应的处理方法。

资源控制器处理的动作

方法
路径
动作
路由名称

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

伪造表单方法

由于HTML表单不能发起PUTPATCHDELETE请求,需要添加一个隐藏的 _method 字段来伪造HTTP请求方式,辅助函数 method_field 可以帮我们做这件事:

{{ method_field(‘PUT‘) }}
部分资源路由

声明资源路由时可以指定该路由处理的动作子集:

Route::resource(‘photo‘, ‘PhotoController‘, [‘only‘ =>
    [‘index‘, ‘show‘]
]);

Route::resource(‘photo‘, ‘PhotoController‘, [‘except‘ =>
    [‘create‘, ‘store‘, ‘update‘, ‘destroy‘]
]);
命名资源路由

默认情况下,所有资源控制器动作都有一个路由名称,然而,我们可以通过传入 names 数组来覆盖这些默认的名字:

Route::resource(‘photo‘, ‘PhotoController‘, [‘names‘ =>
    [‘create‘ => ‘photo.build‘]
]);
命名资源路由参数

默认情况下, Route::resource 将会基于资源名称的单数格式为资源路由创建路由参数,你可以通过在选项数组中传递 parameters 来覆盖这一默认设置。 parameters 应该是资源名称和参数名称的关联数组:

Route::resource(‘user‘, ‘AdminUserController‘, [‘parameters‘ => [
    ‘user‘ => ‘admin_user‘
]]);

上面的示例代码会为资源的 show 路由生成如下URL:

/user/{admin_user}
补充资源控制器

如果有必要在默认资源路由之外添加额外的路由到资源控制器,应该在调用 Route::resource 之前定义这些路由;否则,通过 resource 方法定义的路由可能无意中优先于补充的额外路由:

Route::get(‘photos/popular‘, ‘[email protected]‘);
Route::resource(‘photos‘, ‘PhotoController‘);

注:注意保持控制器的单一职责,如果你发现指向控制器动作的路由超过默认提供的资源控制器动作集合了,考虑将你的控制器分割成更多、更小的控制器。

5、依赖注入 & 控制器
构造函数注入

Laravel 使用服务容器解析所有的 Laravel 控制器,因此,可以在控制器的构造函数中类型声明任何依赖,这些依赖会被自动解析并注入到控制器实例中:

<?php

namespace App\Http\Controllers;

use Illuminate\Routing\Controller;
use App\Repositories\UserRepository;

class UserController extends Controller
{
    /**
     * The user repository instance.
     */
    protected $users;

    /**
     * 创建新的控制器实例
     *
     * @param UserRepository $users
     * @return void
     */
    public function __construct(UserRepository $users)
    {
        $this->users = $users;
    }
}

当然,你还可以类型提示任何 Laravel 契约,如果容器可以解析,就可以进行类型提示。

方法注入

除了构造函数注入之外,还可以在控制器的动作方法中进行依赖的类型提示,例如,我们可以在某个方法中类型提示  Illuminate\Http\Request 实例:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;

class UserController extends Controller
{
    /**
     * 存储新用户
     *
     * @param Request $request
     * @return Response
     */
    public function store(Request $request)
    {
        $name = $request->input(‘name‘);

        //
    }
}

如果控制器方法期望输入路由参数,只需要将路由参数放到其他依赖之后,例如,如果你的路由定义如下:

Route::put(‘user/{id}‘, ‘[email protected]‘);

你需要通过定义控制器方法如下所示来类型提示 Illuminate\Http\Request 并访问路由参数 id

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;

class UserController extends Controller
{
    /**
     * 更新指定用户
     *
     * @param Request $request
     * @param int $id
     * @return Response
     * @translator http://laravelacademy.org
     */
    public function update(Request $request, $id)
    {
        //
    }
}
6、路由缓存

注意:路由缓存不会作用于基于闭包的路由。要使用路由缓存,必须将闭包路由转化为控制器路由。

如果你的应用完全基于控制器路由,可以使用 Laravel 的路由缓存,使用路由缓存将会极大减少注册所有应用路由所花费的时间开销,在某些案例中,路由注册速度甚至能提高100倍!想要生成路由缓存,只需执行 Artisan 命令route:cache:

php artisan route:cache

运行完成后,每次请求都会从缓存中读取路由,记住,如果你添加新的路由需要重新生成路由缓存。因此,只有在项目部署阶段才需要运行 route:cache 命令。

想要移除缓存路由文件,使用 route:clear 命令即可:

php artisan route:clear

时间: 2024-10-06 05:02:04

HTTP层 —— 控制器的相关文章

[Prodinner项目]学习分享_第四部分(完结篇)_Controller层(控制器)

Controller作用: 数据从数据库查询出来后,通过一定的业务逻辑,筛选出来一个结果集,我们最终的目的是要将这个结果集在页面中显示的. Controller就是起到这个作用,将业务逻辑层的结果集调出来,然后通过Model,或者Json的方式返回到View(页面)里. 1.我们需要创建一个Conroller,继承封装好的BaseController. 2.将之前写好的PersonService实例化. 3.获取结果集. -PersonService里有CrudService封装好的,增删改查常

ZendFramework-2.4 源代码 - 关于MVC - View层 - 控制器返回值

<?php class ReturnController extends AbstractActionController { public function returnAction() { // 返回方式一 :会被dipatch处理器Zend\Mvc\View\Http\CreateViewModelListener::createViewModelFromArray(...)的拦截处理 return array('key1' => 'key1value'); // == new View

链路层综述

一. 一些术语 运行链路层协议的任何设备均称为结点 (node). 沿着通信路径连接相邻结点的通信信道称为链路 (link). 二.两种链路层信道 广播信道 用于连接有线局域网.卫星网和混合光纤同轴电缆接入网中的多台主机.需要媒体访问协议来协调帧传输. 点对点通信链路 在诸如长距离链路连接的两台路由器之间,或用户办公室主机与它们所连接的临近以太网交换机之间等场合. 三.链路层提供的服务 成帧 (framing) 即把网络层的数据报封装为适合链路传输的链路层帧. 链路接入 媒体访问控制 (Medi

使用自定义 URL 实现控制器之间的跳转-b

一个app往往有很多界面,而界面之间的跳转也就是对应控制器的跳转,控制器的跳转一般有两种情况 push 或者 modal,push 和 modal 的默认效果是系统提供的 文章配图 1. 概述 系统提供的push和modal方法有时并不能满足实际需求.比如,我们需要根据服务器返回的字段跳到指定的控制器,难道作判断吗?那显然不是最佳解决方案. 其实我们可以这样: NSString *urlStr = @"dariel://twoitem?name=dariel&userid=213213&

[框架模式]经典的模型视图控制器模式MVC

参考:<设计模式> http://blog.csdn.net/u010168160/article/details/43150049 百度百科 引言: Model(模型)是应用程序中用于处理应用程序数据逻辑的部分. 通常模型对象负责在数据库中存取数据. View(视图)是应用程序中处理数据显示的部分. 通常视图是依据模型数据创建的. Controller(控制器)是应用程序中处理用户交互的部分. 通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据. MVC 分层有助于管理复杂的应用程

七色花基本权限系统(13)- 业务层的设计和实现

解耦WebUI层与EntityFramework 在还未实现实体仓储时,登录功能是在控制器中直接初始化EF数据库上下文来实现的,这样也导致WebUI层必须引用EntityFramework.在完成数据层的设计和实现之后,控制器中不再直接使用EF数据库上下文对象,而是通过工作单元去调用实体仓储,其实到了这一步就可以让WebUI层不再依赖EntityFramework.从WebUI层中通过nuget管理的方式移除EF,但要注意的是,EF包含2个dll,其中的EntityFramework.SqlSe

计算机网络——链路层

数据链路层:概述与服务 链路层主要使用的信道包括: 广播信道 : 这种信道采用一对多的广播通信方式,因此过程比较复杂.广播信道上主机众多,我们必须使用专用的共享信道协议来协调这些主机的数据发送 点对点信道 : 这种信道使用一对一的点对点通信方式 链路层提供的服务 链路层协议定义了在链路两端的节点之间交互的分组格式,以及当发送和接受分组时这些节点采取的动作. 链路层协议可能提供的服务包括: 服务 概述 成帧 在每个数据报传输时,用链路层帧将其封装起来.一个帧由首部,数据字段和尾部组成.链路层的数据

URLRewrite地址重定向的实现

URLRewrite就是我们通常说的地址重写,用户得到的全部都是经过处理后的URL地址.其优点有: (1)提高安全性,可以有效的避免一些参数名.ID等完全暴露在用户面前,如果用户随便乱输的话,不符合规则的话直接会返回个404或错误页面,这比直接返回500或一大堆服务器错误信息要好的多. (2)美化URL,去除了那些比如*.do之类的后缀名.长长的参数串等,可以自己组织精简更能反映访问模块内容的URL. (3)更有利于搜索引擎的收入,通过对URL的一些优化,可以使搜索引擎更好的识别与收录网站的信息

SpringMVC + spring3.1.1 + hibernate4.1.0 集成及常见问题总结

一 开发环境 1.动态web工程 2.部分依赖 java代码: hibernate-release-4.1.0.Final.zip hibernate-validator-4.2.0.Final.jar spring-framework-3.1.1.RELEASE-with-docs.zip proxool-0.9.1.jar log4j 1.2.16 slf4j -1.6.1 mysql-connector-java-5.1.10.jar hamcrest 1.3.0RC2 ehcache 2