[PHP] Application controllers (1)

Source: Internet
Author: User
Tags dsn
[PHP] Application controller (i)

The front-end controller has been able to centrally process requests and select the appropriate command in one place, but the command subclass object handles the assignment of the view itself. The ability to use a class (based on the status value returned by command processing) to determine the view and return to the front controller, and then the front controller to invoke the view display, so that the front controller is in the middle of the view layer and the business layer, but also good to separate the command and view . The application controller is a good solution.

The application controller is responsible for mapping the request to the command and mapping the command to the view. It allows you to change the process of the application without needing to modify the core code. It frees the command class and lets the command class focus on its work, including handling input, invoking application logic, and processing results.

An application controller is a class (or set of classes) that helps the front-end control take over the task of processing the request and returns the appropriate view to the front-end controller invocation. So how does application control work? It is the way that command and view work is determined through an XML configuration file. For example, the following XML file (a bit like the way struts does):

 
  
 
  
  
   
    
   sqlite://data/demo.db
  
   
  
   
    
   root
  
   
  
   
    
   root
  
   
  
   
   
    
     
    main
   
    
   
    
     
    main
   
    
   
    
     
    error
   
    
   
    
   
    
     
    list_students
   
    
   
    
   
    
     
    add_student
   
    
   
    
    
     
      
     liststudents
    
     
   
    
   
    
   simple_
    
   
    
     
    Add_student
   
    
     
   
 
  
you can see in the XML can contain , three types of child elements, respectively, the command corresponding to the view, command processing service after the state value, command processing after the jump (jump to another CO Mmand).


from the XML structure, you can see that the command class needs some new attribute status.

Namespace demo\command;/** * Abstract parent Class */abstract class Command {//state value mapping private static $STATUS _strings = Array (        ' Cmd_defau LT ' = 0,        ' cmd_ok ' = 1,        ' cmd_error ' = 2,        ' Cmd_insufficient_data ' and ' 3 ';//current status value private $status = 0;public final function __construct () {//subclass cannot override constructor}/** * Returns status value by Status String * @param unknown_type $staStr */public static Fun Ction status ($stauStr = ' Cmd_default ') {if (empty ($stauStr)) {$stauStr = ' cmd_default ';} Return self:: $STATUS _strings[$stauStr];} /** * Call Subclass Implementation of Doexecute * @param \demo\controller\request $request */public function execute (\demo\controller\request $ Request) {$this->doexecute ($request);} protected abstract function Doexecute (\demo\controller\request $request);}

In the system, there is an assistant class Applicationhelper for configuration that can read the XML configuration. Because the structure of the elements in XML is relatively flexible, a controllermap is required to manage the values in each element and the one by one mapping of the command and view.

Namespace Demo\controller;class Controllermap {private $classrootMap = array ();p rivate $forwardMap = Array ();p rivate $ Viewmap = Array ();p ublic function Addclassroot ($cmd, $classroot) {$this->classrootmap[$cmd] = $classroot;} Public Function Getclassroot ($cmd) {if (Isset ($this->classrootmap[$cmd]) {return $this->classrootmap[$cmd];} return $cmd;} Public Function Addforward ($cmd = ' Default ', $status = 0, $newCmd) {$this->forwardmap[$cmd] [$status] = $NEWCMD;} Public Function Getforward ($cmd, $status) {if (Isset ($this->forwardmap[$cmd [$status])) {return $this forwardmap[$cmd] [$status];} return  null;} Public Function AddView ($cmd = ' Default ', $status = 0, $view) {$this->viewmap[$cmd] [$status] = $view;} Public Function GetView ($cmd, $status) {if (Isset ($this->viewmap[$cmd [$status])) {return $this->viewmap[$cmd] [ $status];} return  null;}}

You first need to get the getoptions of the configuration Applicationhelper class in the XML.

Namespace demo\controller;/** * Helper class: Get XML Configuration * Singleton mode * */class applicationhelper {private static $instance;p rivate $config = ' Data/config.xml ';p rivate function __construct () {}public static function getinstance () {if (Isset (self:: $instance) = = False) {self:: $instance = new self ();} Return self:: $instance;} Public Function init () {///Initialize configuration gets $DSN = \demo\base\applicationregistry::getinstance ()->getdsn () from the serialization file; $camp = \ Demo\base\applicationregistry::getinstance ()->getcontrollermap (); if (Is_null ($DSN) | | is_null ($CAMP)) {$this- >getoptions ();}} /** * Get XML configuration */public function GetOptions () {//XML $this->ensure (file_exists ($this->config), "Could not fin        D options File! ");        $options = @simplexml_load_file ($this->config);        Var_dump ($options);                $this->ensure ($options instanceof \simplexmlelement, ' Could not resolve options file! ');  //
 
  $DSN = (string) $options->dsn;        $this->ensure ($DSN, ' No DSN found! ');                \demo\base\applicationregistry::getinstance ()->setdsn ($DSN); //
  
   $map = new Controllermap (); //
   
    foreach ($options->controller->view as $default _view) {$stauStr = Trim ((string) $default _view[' status '));  $status = \demo\command\command::status ($STAUSTR);  $map->addview (' Default ', $status, (string) $default _view); }    //
    foreach ($options->controller->command as $CVF) {$cmd = Trim ((string) $CVF [' name ']); //</command>
    
     
      if ($cvf->classalias) {$classroot = (string) $cvf->classalias[' name '];  $map->addclassroot ($cmd, $classroot); }// 
      
       , 
       
        if ($cvf->view) {$view = Trim ((string) $cvf->view); $forward = Trim ((string) $CVF->f Orward); $map->addview ($cmd, 0, $view); if ($forward) {$map->addforward ($cmd, 0, $forward);}} 
        
         foreach ($CVF->status as $status) {$stauStr = Trim ((string) $status [' value ']), $view = Trim ((string) $s Tatus->view); $forward = Trim ((string) $status->forward); $stau = \demo\command\command::status ($STAUSTR); if ($view) {$map->addview ($cmd, $stau, $view),} if ($forward) {$map->addforward ($cmd, $stau, $forward);}} } var_dump ($map); \demo\base\applicationregistry::getinstance ()->setcontrollermap ($MAP);} Private function ensure ($expr, $msg) {if (! $expr) {throw new \demo\base\appexception ($msg);}} 
         
        
      

     
    
   
  
 

The process of getting an XML configuration is a time-consuming operation that serializes a Controllermap object into a file, which can then be retrieved by Applicationregistry and cached as a global data.

/** * Application scope */class Applicationregistry extends Registry {private static $instance; Private $freezedir = "./data";    Hard code here, specific to the actual configuration of the private $values = Array ();    Private $mtimes = Array (); Private Function __construct () {}public static function getinstance () {if (Isset (self:: $instance) = = False) {self: : $instance = new self ();} Return self:: $instance;} /** * Get $key data from a serialized file */protected function Get ($key) {$path = $this->freezedir. Directory_separator.        $key;            if (file_exists ($path)) {//Clear file cache Clearstatcache ();            $mtime = Filemtime ($path);             if (Isset ($this->mtimes[$key]) = = False) {$this->mtimes[$key]=0;  }//file has been modified recently, re-deserialized new data if ($mtime > $this->mtimes[$key]) {$data                = File_get_contents ($path);                $this->mtimes[$key] = $mtime; Return ($this->values[$key] = unserialize ($data));        }} if (Isset ($this->values[$key]) = = True) {return $this->values[$key];    } return null;        } protected function set ($key, $val) {$this->values[$key] = $val; $path = $this->freezedir. Directory_separator.        $key;        if (file_exists ($path)) {Touch ($path);        } file_put_contents ($path, serialize ($val));    $this->mtimes[$key]=time ();        Public Function Getdsn () {if (Isset ($this->values[' DSN ')) {return $this->values[' DSN '];    } return Self::getinstance ()->get (' DSN ');    } Public Function Setdsn ($DSN) {return self::getinstance ()->set (' DSN ', $DSN); }/** * * @param \demo\controller\controllermap $map */Public function Setcontrollermap (\demo\controll    Er\controllermap $map) {self::getinstance ()->set (' CMap ', $map); } public Function Getcontrollermap () {if (Isset ($this->values[' cmap ')) {return $this->values[' CMap '];    } return Self::getinstance ()->get (' CMap ');        }/** * gets AppController */Public Function Getappcontroller () {$obj = Self::instance ();            if (!isset ($obj->appcontroller)) {$cmap = $obj->getcontrollermap ();        $obj->appcontroller = new \demo\controller\appcontroller ($CMAP);    } return $obj->appcontroller; }//Some other column getter and setter//...}

To make more complex calls this time, such as forward, it is necessary to simply modify the code of the request class so that it conforms to the call logic.

Namespace demo\controller;/** * Package user request * Requesting */class request {private $properties;p rivate $feedback = Array ();//    Save the business object, you can supply the view using private $objects = Array ();//Save the last executed command object private $lastCommand;    Public Function __construct () {$this->init ();    $this->filterproperties ();    \demo\base\requestregistry::getinstance ()->setrequest ($this);    Public Function __clone () {$this->properties = array (); } Public Function init () {if (Isset ($_server[' Request_method ')) {if ($_server[' Request_method ']) {$thi        S->properties = $_request;    return; }}//command-line mode foreach ($_server[' argv ') as $arg) {if (Strpos ($arg, ' = ')) {list ($key, $val) = Explode    (' = ', $arg);    $this->setproperties ($key, $val);        }}} Public function filterproperties () {//filter user request ...}    Public Function GetProperty ($key) {return $this->properties[$key]; Public Function SetProperties ($key, $val){$this->properties[$key] = $val;    } public Function Getfeedback () {return $feedback;    Public Function Addfeedback ($msg) {Array_push ($this->feedback, $msg);    The Public function getfeedbackstring ($separator = ' \ n ') {return implode (' \ n ', $this->feedback); }/** * * @param \demo\command\command $cmd */Public Function SetCommand (\demo\command\command $cmd    ) {$this->lastcommand = $cmd;    } public Function Getlastcommand () {return $this->lastcommand; }/** * * @param unknown_type $name * @param unknown_type $object */Public function setobject (    $name, $object) {$this->objects[$name] = $object;    Public Function GetObject ($name) {if (Isset ($this->objects[$name]) {return $this->objects[$name];    } return null; }}

The class Controllermap, which can save the mapping relationship, has now been added, modifying the request, Command, Applicationhelper, Applicationregistry , the main is to add, a small number of changes before the code.

The above classes have been able to complete the initialization of the system, including reading XML configuration (applicationhelper), global variable access (Registry);

Then there is the core: Controller and AppController two classes.

  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.