控制器 ================= 控制器æä¾›äº†ä¸€äº›æ–¹æ³•,他们被å«åšactions。Actions是控制器用æ¥å¤„ç†ç”¨æˆ·è¯·æ±‚çš„æ–¹æ³•ã€‚é»˜è®¤æƒ…å†µä¸‹ï¼ŒæŽ§åˆ¶å™¨çš„æ‰€æœ‰å…¬æœ‰çš„æ–¹æ³•éƒ½æ˜ å°„åˆ°ä¸€ä¸ªå¯è®¿é—®çš„URL。Actions是负责解释请求以åŠåˆ›å»ºç”¨æˆ·å“应的。通过的å应是一个渲染视图的形å¼ï¼Œä½†ä¹Ÿæœ‰å…¶ä»–çš„å½¢å¼æ¥å¤„ç†ç”¨æˆ·è¯·æ±‚。 ä¾‹å¦‚ï¼Œå½“ä½ è®¿é—®ä¸€ä¸ªè¿™æ ·çš„URLæ—¶ http://localhost/blog/posts/show/2012/the-post-title ,默认情况下,Phalconæ˜¯è¿™æ ·å¯¹URL进行分解的: +------------------------+----------------+ | **Phalcon Directory** | blog | +------------------------+----------------+ | **Controller** | posts | +------------------------+----------------+ | **Action** | show | +------------------------+----------------+ | **Parameter** | 2012 | +------------------------+----------------+ | **Parameter** | the-post-title | +------------------------+----------------+ 在这个例åä¸ï¼ŒPostControlleræŽ§åˆ¶å™¨ç”¨äºŽæ¥æŽ¥æ”¶ç”¨æˆ·è¯·æ±‚ã€‚ç”±äºŽåœ¨åº”ç”¨ç¨‹åºä¸æ²¡æœ‰å¯¹controllersçš„å˜æ”¾æŒ‡å®šå˜æ”¾ä½ç½®ï¼Œä»–们å¯ä»¥é€šè¿‡ :doc:`autoloaders <loader>` æ¥è‡ªåŠ¨åŠ è½½ä½ çš„controllers目录。 所有的控制器都必须以“Controllerâ€ä¸ºç»“尾,所有的Actions都是以“Actionâ€ç»“å°¾ã€‚ä¸‹é¢æ˜¯ä¸€ä¸ªæŽ§åˆ¶å™¨çš„示例: è¯‘è€…æ³¨ï¼šä¹Ÿå¹¶éžæ‰€æœ‰çš„æŽ§åˆ¶å™¨éƒ½å¿…须以“Controllerâ€ä¸ºç»“尾的,比如我们一般会写一个å为 “ContollerBaseâ€,让他继承自 \Phalcon\Mvc\Controller.ã€€åŒæ—¶æˆ‘们自己应用程åºä¸çš„其他控制器都å†ç»§æ‰¿è‡ª ContollerBase.这么æ¥åšçš„è¯ï¼Œåˆ™æŽ§åˆ¶å™¨ContollerBase就䏿˜¯ä»¥ “Controllerâ€ä¸ºç»“尾了。如果严谨一点æ¥è®²å¯ä»¥è¿™ä¹ˆè¯´ï¼Œæ‰€ä»¥ç”¨äºŽç”¨æˆ·è¯·æ±‚的控制器必须以“Controllerâ€ä¸ºç»“å°¾ .. code-block:: php <?php class PostsController extends \Phalcon\Mvc\Controller { public function indexAction() { } public function showAction($year, $postTitle) { } } å…¶ä»–çš„URI傿•°å°†è¢«å®šä¹‰ä¸ºAction傿•°ï¼Œå› æ¤ä½ å¯ä»¥å¾ˆå®¹æ˜“的使用局部å˜é‡æ¥è®¿é—®è¿™äº›å‚数。控制器继承自 :doc:`Phalcon\\Mvc\\Controller <../api/Phalcon_Mvc_Controller>` 。 è¿™æ ·ä¸€æ¥ï¼Œä½ 的控制器就很方便的æä¾›åº”用æœåŠ¡äº† Dispatch Loop ------------- å…¶ä»–çš„URI傿•°å°†è¢«å®šä¹‰ä¸ºAction傿•°ï¼Œå› æ¤ä½ å¯ä»¥å¾ˆå®¹æ˜“的使用局部å˜é‡æ¥è®¿é—®è¿™äº›å‚数。控制器继承自 :doc:`Phalcon\\Mvc\\Controller <../api/Phalcon_Mvc_Controller>` 。 è¿™æ ·ä¸€æ¥ï¼Œä½ 的控制器就很方便的访问应用程åºä¸çš„å…¶ä»–æœåŠ¡äº† .. code-block:: php <?php class PostsController extends \Phalcon\Mvc\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(array( "controller" => "users", "action" => "signin" )); } } 如果用户没有æƒé™è®¿é—®æŸä¸ªç‰¹å®šçš„动作,然åŽå°†è¢«è½¬å‘到UsersController控制器的signinAction .. code-block:: php <?php class UsersController extends \Phalcon\Mvc\Controller { public function indexAction() { } public function signinAction() { } } 应用程åºä¸å¹¶æ²¡æœ‰é™åˆ¶åˆ†å‘器的跳转次数,åªè¦ä»–们ä¸å¯¼è‡´æ»å¾ªçŽ¯ï¼Œå¯ä»¥æ£å¸¸åœæ¢å³å¯ã€‚如果程åºé€»è¾‘ä¸å†æ²¡æœ‰è·³è½¬åˆ°å…¶ä»–çš„Action,程åºå°†è‡ªåŠ¨è°ƒç”¨MVC的视图层 :doc:`Phalcon\\Mvc\\View <../api/Phalcon_Mvc_View>`. åˆå§‹åŒ–控制器 ------------------------ :doc:`Phalcon\\Mvc\\Controller <../api/Phalcon_Mvc_Controller>` æä¾›åˆå§‹åŒ–的方法,它最先执行,注æ„:"__construct" çš„åˆå§‹åŒ–æ–¹æ³•åœ¨è¿™é‡Œä¸æŽ¨è使用。 .. code-block:: php <?php class PostsController extends \Phalcon\Mvc\Controller { public $settings; public function initialize() { $this->settings = array( "mySetting" => "value" ); } public function saveAction() { if ($this->settings["mySetting"] == "value") { //... } } } 访问注入æœåŠ¡ ------------------ 如果控制器继承自 :doc:`Phalcon\\Mvc\\Controller <../api/Phalcon_Mvc_Controller>` ,那么它将å¯ä»¥å¾ˆæ–¹ä¾¿çš„访问应用程åºå®¹å™¨ä¸çš„å…¶ä»–æœåŠ¡ã€‚ä¾‹å¦‚ï¼Œæˆ‘ä»¬æ³¨å†Œäº†ä¸€ä¸ªè¿™æ ·çš„æœåŠ¡ï¼š .. code-block:: php <?php $di = new Phalcon\DI(); $di->set('storage', function(){ return new Storage('/some/directory'); }, true); ç„¶åŽï¼Œæˆ‘们å¯ä»¥é€šè¿‡ä»¥ä¸‹æ–¹å¼è®¿é—®é‚£äº›æœåŠ¡ï¼š .. code-block:: php <?php class FilesController extends \Phalcon\Mvc\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'); } } å¦‚æžœä½ æ£åœ¨ä½¿ç”¨Phalconæ¡†æž¶ï¼Œä½ å¯ä»¥é˜…读一下DI :doc:`by default <di>` 请求和å“应 -------------------- å‡è®¾ï¼Œè¯¥æ¡†æž¶å·²ç»æä¾›äº†ä¸€ç»„预置的æœåŠ¡ã€‚æˆ‘ä»¬å°†è§£é‡Šä»–ä»¬å¦‚ä½•ä¸Žhttp相互å调工作。"request"æœåŠ¡æ˜¯ :doc:`Phalcon\\Http\\Request <../api/Phalcon_Http_Request>` 的一个实例对象, "response"是 :doc:`Phalcon\\Http\\Response <../api/Phalcon_Http_Response>` 的一个实例对象,它负责å‘客户端å‘é€å“应内容。 .. code-block:: php <?php class PostsController extends Phalcon\Mvc\Controller { public function indexAction() { } public function saveAction() { // Check if request has made with POST if ($this->request->isPost() == true) { // Access POST data $customerName = $this->request->getPost("name"); $customerBorn = $this->request->getPost("born"); } } } The response object is not usually used directly, but is built up before the execution of the action, sometimes - like in an afterDispatch event - it can be useful to access the response directly: .. code-block:: php <?php class PostsController extends Phalcon\Mvc\Controller { public function indexAction() { } public function notFoundAction() { // Send a HTTP 404 response header $this->response->setStatusCode(404, "Not Found"); } } å¦ä¹ 更多的关于HTTPçŽ¯å¢ƒç›¸å…³çš„æ–‡ç« ï¼Œè¯·æŸ¥é˜… :doc:`request <request>` ä»¥åŠ :doc:`response <response>`. Session æ•°æ® ------------ Sessions help us maintain persistent data between requests. You could access a :doc:`Phalcon\\Session\\Bag <../api/Phalcon_Session_Bag>` from any controller to encapsulate data that need to be persistent. .. code-block:: php <?php class UserController extends Phalcon\Mvc\Controller { public function indexAction() { $this->persistent->name = "Michael"; } public function welcomeAction() { echo "Welcome, ", $this->persistent->name; } } 注入æœåŠ¡æ›¿ä»£æŽ§åˆ¶å™¨ ----------------------------- 控制器å¯ä»¥æ³¨å†Œæˆä¸ºæœåŠ¡ï¼Œè¿™æ ·çš„è¯ï¼Œç”¨æˆ·çš„è¯·æ±‚éƒ½ä¼šä»Žæ³¨å†Œçš„æŽ§åˆ¶å™¨èŽ·å¾—ã€‚å› æ¤ï¼Œç”¨æ¤ç§åŠžæ³•å¯ä»¥å¾ˆå®¹æ˜“çš„å–代其他控制器。 .. code-block:: php <?php //Register a controller as a service $di->set('IndexController', function() { $component = new Component(); return $component; }); 译者注: 以上例æ¥è¯´æ˜Žï¼Œå¦‚æžœè¦è®¿é—® /index/index çš„è¯ï¼Œåˆ™éœ€è¦åœ¨ç±» Component ä¸ç¼–写 indexAction() 方法。å³å’ŒæŽ§åˆ¶å™¨ä¸çš„action写法是相åŒçš„ã€‚åŒæ—¶ï¼Œå³ä½¿æŽ§åˆ¶å™¨ç›®å½•å˜åœ¨ IndexController,也将ä¸å†è®¿é—®ã€‚而是直接输出 Componentä¸indexAction()的内容 创建一个基础控制器类 -------------------------- 在应用程åºçš„æŽ§åˆ¶å™¨ä¸ç»å¸¸ä¼šéœ€è¦è®¿é—®æŽ§åˆ¶åˆ—表,多è¯è¨€ï¼Œç¼“å˜ï¼Œæ¨¡æ¿å¼•擎ç‰ã€‚åœ¨è¿™ç§æƒ…å†µä¸‹ï¼Œæˆ‘ä»¬ä¸€èˆ¬å»ºè®®ä½ åˆ›å»ºä¸€ä¸ª “base controllerâ€,以防é‡å¤é€ è½®åï¼Œä¿æŒä»£ç DRY_ .æŽ§åˆ¶å™¨åªæ˜¯ä¸€ä¸ªç®€å•的类文件,他è¦ç»§æ‰¿è‡ª :doc:`Phalcon\\Mvc\\Controller <../api/Phalcon_Mvc_Controller>` ,其他的控制器å†ç»§æ‰¿è‡ª "base controller"ï¼Œè¿™æ ·å°±å¯ä»¥æ‹¥æœ‰åŸºç±»æŽ§åˆ¶å™¨ä¸çš„é€šç”¨åŠŸèƒ½äº†ï¼Œä½ çš„ä»£ç 就会更整æ´ä¸€äº›ã€‚ 这个类å¯ä»¥æ”¾åˆ°ä»»ä½•目录下,但按照一般的规则æ¥è®²ï¼Œæˆ‘们推èä½ æŠŠå®ƒæ”¾åˆ°æŽ§åˆ¶å™¨æ–‡ä»¶å¤¹ä¸ï¼Œæ¯”如 apps/controllers/ControllerBase.php 。我们å¯èƒ½ä¼šéœ€è¦è¿™ä¸ªæ–‡ä»¶ï¼Œä½ å¯ä»¥ç›´æŽ¥åœ¨ç¨‹åºä¸å¼•入,或者通过Phalconçš„autoloader引入: .. code-block:: php <?php require "../app/controllers/ControllerBase.php"; 一般通用的功能组件,我们å¯ä»¥å†™åˆ°è¿™ä¸ªæ–‡ä»¶ä¸ï¼Œæ¯”如 (actions,methods, propertiesç‰): .. code-block:: php <?php class ControllerBase extends \Phalcon\Mvc\Controller { /** * This action is available for multiple controllers */ public function someAction() { } } 其他继承自ControllerBase的控制器,会自动获得通用组件。 译者注: åªè¦æ˜Žç™½ç±»ç»§æ‰¿æ˜¯æ€Žä¹ˆå›žäº‹ï¼Œè¿™å—å°±éžå¸¸å¥½ç†è§£äº†ã€‚ .. code-block:: php <?php class UsersController extends ControllerBase { } 译者补充: æˆ‘åœ¨è¿™é‡Œå¤šåŠ ä¸€ä¸ªä¾‹åï¼Œä½ å°±å¯ä»¥å¾ˆå®¹æ˜“的明白 base controller的用处了。 比如,我们一般会在控制器ä¸åšè·³è½¬æ“作,一般会用到 dispatcherçš„ forward方法。但这个forwardæ–¹æ³•çš„å‚æ•°æ˜¯ä¸€ä¸ªæ•°ç»„,需è¦è¿™æ ·å†™ï¼š .. code-block:: php <?php class UsersController extends ControllerBase { public function authAction() { ..... //valiate code $this->dispatcher->forward(array( 'controller' => 'users', 'action' => 'login' ) ); } } 以上é¢ç¤ºä¾‹ä¸çš„写法æ¥è¯´ï¼Œä¼šæœ‰äº›éº»çƒ¦ã€‚那么我们需è¦åœ¨ base controllerä¸åŠ å…¥ä¸€ä¸ªè‡ªå®šä¹‰çš„ forward 方法。 .. code-block:: php <?php class ControllerBase extends \Phalcon\Mvc\Controller { protected function forward($uri){ $uriParts = explode('/', $uri); return $this->dispatcher->forward( array( 'controller' => $uriParts[0], 'action' => $uriParts[1] ) ); } } 冿¬¡æ¥ä¿®æ”¹ UsersControllerä¸çš„authAction方法: .. code-block:: php <?php class UsersController extends ControllerBase { public function authAction() { ..... //valiate code $this->forward('users/login'); } } æ˜¯ä¸æ˜¯éžå¸¸æ–¹ä¾¿äº†ï¼Ÿ 控制器ä¸çš„事件 --------------------- 控制器本身也å¯ä»¥å……当监å¬çš„身份,通过 :doc:`dispatcher <dispatching>` 事件,在控制器ä¸å®žçް dispatcher的事件方法,控制器的方法åè¦ä¸Žäº‹ä»¶å相åŒã€‚è¿™æ ·çš„è¯ï¼Œä½ å°±å¯ä»¥å¾ˆæ–¹ä¾¿çš„在actions执行å‰åŽé€šè¿‡é’©ç‚¹æ‰§è¡Œå…¶ä»–内容: .. code-block:: php <?php class PostsController extends \Phalcon\Mvc\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"); return false; } } public function afterExecuteRoute($dispatcher) { // Executed after every found action } } .. _DRY: http://en.wikipedia.org/wiki/Don't_repeat_yourself