ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] # 控制器 ## 使用控制器 操作是处理请求的控制器上的方法。默认情况下,控制器上的所有公共方法都映射到操作,并且可由URL访问。操作负责解释请求和创建响应。通常,响应采用渲染视图的形式,但也有其他方法可以创建响应。 例如,当您访问这样的URL时:`http://localhost/blog/posts/show/2015/the-post-title` 默认情况下,Phalcon将分解每个部分,如下所示: | 描述 | Slug | | --------------------- | -------------- | | **Phalcon目录** | blog | | **Controller** | posts | | **Action** | show | | **Parameter** | 2015 | | **Parameter** | the-post-title | 在这种情况下,`PostsController`将处理此请求。将控制器放在应用程序中没有特殊的位置,可以使用 `Phalcon\Loader`加载它们,因此您可以根据需要自由组织控制器。 控制器必须具有后缀`Controller`,同时操作后缀`Action`。控制器的样本如下: ```php <?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public function indexAction() { } public function showAction($year, $postTitle) { } } ``` 其他URI参数被定义为操作参数,因此可以使用局部变量轻松访问它们。控制器可以选择扩展`Phalcon\Mvc\Controller`。通过这样做,控制器可以轻松访问应用程序服务。 根据需要处理没有默认值的参数。在PHP中照常设置参数的可选值: ```php <?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public function indexAction() { } public function showAction($year = 2015, $postTitle = 'some default title') { } } ``` 参数的分配顺序与它们在路径中传递的顺序相同。您可以通过以下方式从其名称中获取任意参数: ```php <?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public function indexAction() { } public function showAction() { $year = $this->dispatcher->getParam('year'); $postTitle = $this->dispatcher->getParam('postTitle'); } } ``` ## 调度循环 调度循环将在Dispatcher中执行,直到没有剩余的动作要执行。在前面的示例中,只执行了一个操作。现在我们将看到`forward()` 方法如何通过将执行转发到不同的控制器/操作来在分派循环中提供更复杂的操作流。 ```php <?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public function indexAction() { } public function showAction($year, $postTitle) { $this->flash->error( "You don't have permission to access this area" ); // Forward flow to another action $this->dispatcher->forward( [ 'controller' => 'users', 'action' => 'signin', ] ); } } ``` 如果用户没有访问某个操作的权限,那么他们将被转发到`UsersController`中的 `signin` 操作。 ```php <?php use Phalcon\Mvc\Controller; class UsersController extends Controller { public function indexAction() { } public function signinAction() { } } ``` 您可以在应用程序中使用`forwards`没有限制,只要它们不会导致循环引用,此时您的应用程序将停止。如果调度循环没有要调度的其他操作,调度程序将自动调用由`Phalcon\Mvc\View`管理的MVC的视图层。 ## 初始化控制器 `Phalcon\Mvc\Controller` 提供了 `initialize()` 方法,该方法在控制器上执行任何操作之前首先执行。不建议使用 `__construct()` 方法。 ```php <?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public $settings; public function initialize() { $this->settings = [ 'mySetting' => 'value', ]; } public function saveAction() { if ($this->settings['mySetting'] === 'value') { // ... } } } ``` >[warning] 仅当`beforeExecuteRoute`事件成功执行时,才会调用`initialize()`方法。这样可以避免初始化程序中的应用程序逻辑在未经授权的情况下执行。 ```php <?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public function onConstruct() { // ... } } ``` >[warning] 请注意,即使控制器中不存在要执行的操作或用户无权访问它(根据开发人员提供的自定义控件访问权限),也会执行`onConstruct()`方法。 ## 注入服务 如果控制器扩展`Phalcon\Mvc\Controller`,则可以轻松访问应用程序中的服务容器。例如,如果我们注册了这样的服务: ```php <?php use Phalcon\Di; $di = new Di(); $di->set( 'storage', function () { return new Storage( '/some/directory' ); }, true ); ``` 然后,我们可以通过多种方式访问​​该服务: ```php <?php use Phalcon\Mvc\Controller; class FilesController extends Controller { public function saveAction() { // Injecting the service by just accessing the property with the same name $this->storage->save('/some/file'); // Accessing the service from the DI $this->di->get('storage')->save('/some/file'); // Another way to access the service using the magic getter $this->di->getStorage()->save('/some/file'); // Another way to access the service using the magic getter $this->getDi()->getStorage()->save('/some/file'); // Using the array-syntax $this->di['storage']->save('/some/file'); } } ``` 如果您将Phalcon用作全栈框架,则可以阅读框架中默认提供的服务。 ## 请求和响应 假设框架提供了一组预先注册的服务。我们将解释如何与HTTP环境进行交互。`request`服务包含`Phalcon\Http\Request` 的实例,`response` 包含`Phalcon\Http\Response` ,表示将要发送回客户端的内容。 ```php <?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public function indexAction() { } public function saveAction() { // Check if request has made with POST if ($this->request->isPost()) { // Access POST data $customerName = $this->request->getPost('name'); $customerBorn = $this->request->getPost('born'); } } } ``` 响应对象通常不直接使用,但是在执行操作之前构建,有时 - 就像在`afterDispatch`事件中一样 - 直接访问响应会很有用: ```php <?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public function indexAction() { } public function notFoundAction() { // Send a HTTP 404 response header $this->response->setStatusCode(404, 'Not Found'); } } ``` 在文档`请求`和`响应`中了解有关HTTP环境的更多信息。 ## 会话数据 会话帮助我们维护请求之间的持久数据。您可以从任何控制器访问`Phalcon\Session\Bag`以封装需要持久化的数据: ```php <?php use Phalcon\Mvc\Controller; class UserController extends Controller { public function indexAction() { $this->persistent->name = 'Michael'; } public function welcomeAction() { echo 'Welcome, ', $this->persistent->name; } } ``` ## 使用服务作为控制器 服务可以充当控制器,始终从服务容器请求控制器类。因此,使用其名称注册的任何其他类都可以轻松替换控制器: ```php <?php // Register a controller as a service $di->set( 'IndexController', function () { $component = new Component(); return $component; } ); // Register a namespaced controller as a service $di->set( 'Backend\Controllers\IndexController', function () { $component = new Component(); return $component; } ); ``` ## 控制器中的事件 控制器自动充当`调度`程序事件的侦听器,使用这些事件名称实现方法允许您在执行操作之前/之后实现挂钩点: ```php <?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public function beforeExecuteRoute($dispatcher) { // This is executed before every found action if ($dispatcher->getActionName() === 'save') { $this->flash->error( "You don't have permission to save posts" ); $this->dispatcher->forward( [ 'controller' => 'home', 'action' => 'index', ] ); return false; } } public function afterExecuteRoute($dispatcher) { // Executed after every found action } } ```