[PHP] Application Controller (ii)
In order to have a clearer understanding of the structure of the overall implementation of the application controller, the classes required in the code have been implemented before, and only the core parts are now available: AppController and controller.
Namespace demo\controller;/** * Controller */class Controller {private $appHelper;//cannot be instantiated, only through Controller::run () The way to execute Private function __construct () {}public static function run () {$instance = new self ();//load Config $instance->init (); /Processing request $instance->handlereuqest ();} Private Function init () {$appHelper = \demo\controller\applicationhelper::getinstance (); $appHelper->init ();} Private Function Handlereuqest () {$request = new \demo\controller\request (); $appController = \demo\base\ Applicationregistry::getinstance ()->getappcontroller ();//execute All command, there may be forwardwhile ($cmd = $ Appcontroller->getcommand ($request)) {//Var_dump ($cmd); $cmd->execute ($request);//Set current command to executed $ Request->setlastcommand ($cmd);} Get View $view = $appController->getview ($request);//Display View $this->invokeview ($view);/* $cmdReslover = new \demo\ Command\commandreslover (); $cmd = $cmdReslover->getcommand ($request); $cmd->execute ($request); */}private function Invokeview ($view) {include ("demo/view/{$View}.php "); exit ();}}
The while loop inside the HandleRequest () is to be handled in order to be possible , the value of the element is the corresponding command subclass, these , And the relationship has been mapped to Controllermap.
Controller execution Process:
1) Read the XML configuration to the Controllermap object;
2) Get $request;
3) by AppController parsing $request->getproperty (' cmd '), return to $cmd;
4) $cmd->execute ($request), $request->setproperties (' cmd ', $forward) If there is a cmd corresponding $forward in Controllermap, jump to 3) , otherwise jump to 5);
5) Obtain view $view by Appcontroller->getview ($request);
6) Call View Invokeview ($view);
Application Controller AppController:
Namespace demo\controller;/** * AppController */class appcontroller {private static $BASECMD;p rivate static $DEFAULTCMD; private $controllerMap;//Mark a command that has been executed to prevent the forward loop private $invoked = Array ();p ublic function __construct (\demo\ Controller\controllermap $camp) {if (!isset (self:: $BASECMD)) {self:: $BASECMD = new \reflectionclass (' \demo\command\ Command '); Self:: $DEFAULTCMD = new \demo\command\defaultcommand ();} $this->controllermap = $camp;} Public Function GetView (\demo\controller\request $request) {$view = $this->getresource ($request, ' view '); return $ View;} Public Function Getforward (\demo\controller\request $request) {$forward = $this->getresource ($request, ' forward '); if ($forward) {//Set forward for new request $request->setproperties (' cmd ', $forward);} return $forward;} /** * GetView, Getforward * @param \demo\controller\request $request * @param string $resType */private function Getresourc E (\demo\controller\request $request, $resType) {$cmd = $request->getproperty (' cmd '); $previous = $request->getlastcommand (); $status = $previous->getstatus (); $status = $status? $status: 0; $acquire = "get{$resType}";//Get view or forward by the specified priority $resource = $this->controllermap-> $acquire ($cmd, $ Status), if (! $resource) {$resource = $this->controllermap-> $acquire (' Default ', $status);} if (! $resource) {$resource = $this->controllermap-> $acquire ($cmd, 0);} if (! $resource) {$resource = $this->controllermap-> $acquire (' default ', 0);} return $resource;} Public Function GetCommand (\demo\controller\request $request) {$previous = $request->getlastcommand (); if (!$ Previous) {//current for first request $cmd = $request->getproperty (' cmd '), if (! $cmd) {//cmd is empty, return default$request->setproperties (' cmd ', ' Default '); return self:: $DEFAULTCMD;} } else {//returns Forward$cmd = $this->getforward ($request); if (! $cmd) {return null;}} Command object $CMDOBJ = $this->reslovecommand ($cmd), if (! $cmdObj) {throw new \demo\base\appexception ("' Command {$ CMD} not found! ");} Determine if forward cycle $cmdclass= Get_class ($CMDOBJ), if (Isset ($this->invoked[$cmdClass])) {throw new \demo\base\appexception (' Circular Forwarding! ');} $this->invoked[$cmdClass] = True;return $cmdObj;} /** * Get $cmd corresponding mapping from Controllermap * @param string $cmd */public function Reslovecommand ($cmd) {$classroot = $this->contr Ollermap->getclassroot ($cmd); $sep = directory_separator; $filePath = "demo{$sep}command{$sep} {$classroot}.php"; $ ClassName = "\\demo\\command\\{$classroot}", if (file_exists ($filePath)) {@require_once $filePath; if (Class_exists ($ ClassName) {$cmdClass = new \reflectionclass ($className), if ($cmdClass->issubclassof (self:: $BASECMD)) {return $ Cmdclass->newinstance ();} }}return null;}}
Note that the request object, GetResource and GetCommand, are handled according to the CMD or lastcommand inside the request object.
the application controller still needs to get cmd from the requested URL to judge the call command, but it can take advantage of the process of controlling the program, and can arrange different views for a page that can produce many different feedbacks (such as forms, which may be error after submission, Success and other feedback views).
The controller and AppController are all done, so take a look at a concrete example.
A specific command subclass, Login:
namespace demo\command;require_once ' demo/command/command.php '; require_once ' demo/base/registry.php '; class Login Extends Command {protected function Doexecute (\demo\controller\request $request) {$userName = $request->getproperty (' UserName '); $password = $request->getproperty (' password '), if (! $userName | |! $password) {return self::status (' CMD _insufficient_data ');} if ($userName = = ' Root ' && $password = = ' root ') {return self::status (' Cmd_ok ');} else {return self::status (' Cmd_er ROR ');}}}
For the following three URL requests, the controller will get the expected results:
Runner.php?cmd=login&username=root&password //Cmd_insufficient_data runner.php?cmd=login& Username=root&password=root//CMD_OK runner.php?cmd=login&username=root&password=123//CMD_ERROR
The following is the code for the portal file runner.php:
Use demo\controller\controller;require_once ' demo/controller/controller.php '; Controller::run ();
The request is now processed and the program flow is controlled. Application controllers are rarely used in general cases. If you only need to implement a single entry function, a portal file (runner.php) directly resolves the URL to complete.
The controller layer is complete, and then the persistence layer needs to be implemented.