控制器

目录

基础介绍

控制器是一个负责接受用户请求和处理模型、类库、视图之间交互的类. 通常情况下,控制器负责抽取模型里的数据然后数据填入到视图中返回给用户.

控制器是现代的网络开发中用来处理应用程序逻辑的最普遍的方式. Laravel中同样允许用户把应用程序逻辑放入路由声明中. 详细参阅路由文档.新接触Laravel的用户还是鼓励从控制器开始开发的,因为路由声明的应用程序逻辑所能实现的一切功能控制器都可以实现.

控制器类文件应当放在application/controllers文件夹中,需要继承Base_Controller类.Laravel初始包中已经存在了一个叫做Home_Controller的类.

创建一个简单的控制器:

class Admin_Controller extends Base_Controller
{

    public function action_index()
    {
        //
    }

}

动作是用来接受网络访问的控制器内的方法 . 动作方法应当以"action_"前缀开始. 所有其他形式命名的方法无论他们的作用域如何都是无法被访问到的.

提示: Base_Controller类继承自Laravel的控制器主类, 这个类默认给你提供了一些方便调用的常用的方法.

控制器路由

你要意识到, Laravel中所有的路由都要被明确的定义, 其中包括跳转到控制器的路由. 也就是说, 没有通过路由注册的控制器是不可以被访问到的. 可以通过控制器路由注册自动暴露控制器的所有方法. 控制器路由的注册被定义在application/routes.php文件中.

详细请参阅路由文档的控制器路由一节.

Bundle控制器

Bundles是Laravel的模块化的软件包管理系统. Bundle可以被简单的配置以实现处理程序请求. 前往bundles详细介绍文档.

创建一个属于bundle的控制器和创建一个普通的控制器的方式是完全相同的,唯一要保证的是控制器的前缀要是bundle的名称,所以如果你的bundle叫做"admin"的话,控制器类需要这样写:

创建一个bundle控制器:

class Admin_Home_Controller extends Base_Controller
{

    public function action_index()
    {
        return "Hello Admin!";
    }

}

但是怎样注册一个bundle控制器的路由呢? 非常简单,样子就像这样:

注册一个bundle控制器的路由:

Route::controller('admin::home');

很好! 现在我们就可以通过浏览器访问"admin"bundle的home控制器了!

提示:在Laravel里,双冒号的语法形式被用来标识bundle. 更多信息前往bundles详细介绍文档.

动作过滤器

动作过滤器是被注册的一个可以在控制器动作之前或者之后运行的方法.在Laravel里你不仅可以注册一个针对某一个控制器动作的的过滤器,你甚至可以显示的声明那种类型的请求(post, get, put, 和 delete)会被过滤器拦截.

你可以在控制器的构造方法了声明注册一个动作过滤器.

为所有动作绑定一个过滤器:

$this->filter('before', 'auth');

这个例子表示,一个叫做'auth'的过滤将在这个控制器的所有动作执行之前执行. 这个'auth'的过滤器可以在application/routes.php中被找到. auth用来过滤验证用户登录,如果没有登录将其重定向到"登录"页面.

为特定的动作绑定一个过滤器:

$this->filter('before', 'auth')->only(array('index', 'list'));

这个例子表示,一个叫做'auth'的过滤将在这个控制器的action_index()和action_list()动作执行之前执行. 用户在访问这两个动作方法之前必须登录,其他的方法则没有这个限制.

为特定的动作之外的动作绑定一个过滤器:

$this->filter('before', 'auth')->except(array('add', 'posts'));

和上一个例子相仿,一个叫做'auth'的过滤将在部分动作执行之前执行. 不同的是上个例子标识那些动作需要过滤,而"except"标识那些动作不需要被过滤. 相对于"only",这种方法更安全一些,因为如果使用"only"方法,你有可能会忘记添加新增加的动作方法到only方法中而导致用户意外访问.

所有的post请求发生时执行一个过滤器:

$this->filter('before', 'csrf')->on('post');

这个例子展示了如何让一个过滤器只在特定的Http请求是起作用. 当post请求被接受到时执行"csrf(防跨站提交)"的验证. 这个验证方法是Laravel内置的,你可以在application/routes.php文件中找到它.

更多相关:

控制器层级

控制器也许会被放到application/controllers文件夹下的子文件夹之中.

controllers/admin/panel.php文件夹下定义一个控制器类.

class Admin_Panel_Controller extends Base_Controller
{

    public function action_index()
    {
        //
    }

}

使用"点"语法注册一个层级的控制器:

Route::controller('admin.panel');

提示: 当用到路由器层级的时候, 你的路由注册顺序一定要从文件夹层级多的到文件夹层级少的,这样可以避免路由覆盖.

访问控制器中的"index"动作:

http://localhost/admin/panel

控制器布局

控制器布局的知识请参阅 模板文档.

表述性状态转移(REST)

除了以"action_"作为动作前缀之外, 你也可以用HTTP请求方式的的前缀来标识控制器动作.

添加一个REST属性支持到控制器中:

class Home_Controller extends Base_Controller
{

    public $restful = true;

}

绑定REST到控制器动作:

class Home_Controller extends Base_Controller
{

    public $restful = true;

    public function get_index()
    {
        //
    }

    public function post_index()
    {
        //
    }

}

这种方式在CRUD操作中非常有用,你可以区分出不同的请求逻辑,用来填充表单和保存数据.

依赖注入

如果你致力于编写可测试的代码,你也许希望在控制器构造函数之外注入对象. 没问题你可以在IoC容器中注册你的控制器,当控制器注册时请以controller作为前缀,所以在application/start.php文件中我们可以像这样注册控制器:

IoC::register('controller: user', function()
{
    return new User_Controller;
});

当一个请求进入时,Laravel会自动确定出是否这个控制器在容器中被注册,如果被注册将会利用控制反转容器去处理控制器实例.

提示: 在使用依赖注入之前,你也许需要阅读Laravel的优美的IoC容器文档.

控制器工厂

如果你想让自己的控制器实例变得更可控, 比如第三方的控制反转容器, 你会用到Laravel的控制器工厂.

注册一个处理控制器实例的事件监听:

Event::listen(Controller::factory, function($controller)
{
    return new $controller;
});

这个监听时间会收到需要处理的控制器类名称,你所要做的就是返回这个控制器的实例. (返回之前你可以对它操作你想做的一切)