zend framework教程之分发器zend_controller_dispatcher用法详解,zendframework本文实例讲述了zend framework教程之分发器zend_controller_dispatcher用法。分享给大家供大家参考,具体如下:
分发器的具体实现
zend framework的分发器zend_controller_dispatcher设计主要有,如下类和接口组成:
├── dispatcher
│   ├── abstract.php
│   ├── exception.php
│   ├── interface.php
│   └── standard.php
zend_controller_dispatcher_interface
定义了分发器提供的基本和标准功能。
interface zend_controller_dispatcher_interface{  public function formatcontrollername($unformatted);  public function formatmodulename($unformatted);  public function formatactionname($unformatted);  public function isdispatchable(zend_controller_request_abstract $request);  public function setparam($name, $value);  public function setparams(array $params);  public function getparam($name);  public function getparams();  public function clearparams($name = null);  public function setresponse(zend_controller_response_abstract $response = null);  public function getresponse();  public function addcontrollerdirectory($path, $args = null);  public function setcontrollerdirectory($path);  public function getcontrollerdirectory();  public function dispatch(zend_controller_request_abstract $request, zend_controller_response_abstract $response);  public function isvalidmodule($module);  public function getdefaultmodule();  public function getdefaultcontrollername();  public function getdefaultaction();}
zend_controller_dispatcher_abstract
实现了zend_controller_dispatcher_interface接口,提供了分发器提供的基本和标准功能的抽象父类。
setparams($params);  }  public function formatcontrollername($unformatted)  {    return ucfirst($this->_formatname($unformatted)) . 'controller';  }  public function formatactionname($unformatted)  {    $formatted = $this->_formatname($unformatted, true);    return strtolower(substr($formatted, 0, 1)) . substr($formatted, 1) . 'action';  }  public function _verifydelimiter($spec)  {    if (is_string($spec)) {      return (array) $spec;    } elseif (is_array($spec)) {      $allstrings = true;      foreach ($spec as $delim) {        if (!is_string($delim)) {          $allstrings = false;          break;        }      }      if (!$allstrings) {        require_once 'zend/controller/dispatcher/exception.php';        throw new zend_controller_dispatcher_exception('word delimiter array must contain only strings');      }      return $spec;    }    require_once 'zend/controller/dispatcher/exception.php';    throw new zend_controller_dispatcher_exception('invalid word delimiter');  }  public function getworddelimiter()  {    return $this->_worddelimiter;  }  public function setworddelimiter($spec)  {    $spec = $this->_verifydelimiter($spec);    $this->_worddelimiter = $spec;    return $this;  }  public function getpathdelimiter()  {    return $this->_pathdelimiter;  }  public function setpathdelimiter($spec)  {    if (!is_string($spec)) {      require_once 'zend/controller/dispatcher/exception.php';      throw new zend_controller_dispatcher_exception('invalid path delimiter');    }    $this->_pathdelimiter = $spec;    return $this;  }  protected function _formatname($unformatted, $isaction = false)  {    // preserve directories    if (!$isaction) {      $segments = explode($this->getpathdelimiter(), $unformatted);    } else {      $segments = (array) $unformatted;    }    foreach ($segments as $key => $segment) {      $segment    = str_replace($this->getworddelimiter(), ' ', strtolower($segment));      $segment    = preg_replace('/[^a-z0-9 ]/', '', $segment);      $segments[$key] = str_replace(' ', '', ucwords($segment));    }    return implode('_', $segments);  }  public function getfrontcontroller()  {    if (null === $this->_frontcontroller) {      require_once 'zend/controller/front.php';      $this->_frontcontroller = zend_controller_front::getinstance();    }    return $this->_frontcontroller;  }  public function setfrontcontroller(zend_controller_front $controller)  {    $this->_frontcontroller = $controller;    return $this;  }  public function setparam($name, $value)  {    $name = (string) $name;    $this->_invokeparams[$name] = $value;    return $this;  }  public function setparams(array $params)  {    $this->_invokeparams = array_merge($this->_invokeparams, $params);    return $this;  }  public function getparam($name)  {    if(isset($this->_invokeparams[$name])) {      return $this->_invokeparams[$name];    }    return null;  }  public function getparams()  {    return $this->_invokeparams;  }  public function clearparams($name = null)  {    if (null === $name) {      $this->_invokeparams = array();    } elseif (is_string($name) && isset($this->_invokeparams[$name])) {      unset($this->_invokeparams[$name]);    } elseif (is_array($name)) {      foreach ($name as $key) {        if (is_string($key) && isset($this->_invokeparams[$key])) {          unset($this->_invokeparams[$key]);        }      }    }    return $this;  }  public function setresponse(zend_controller_response_abstract $response = null)  {    $this->_response = $response;    return $this;  }  public function getresponse()  {    return $this->_response;  }  public function setdefaultcontrollername($controller)  {    $this->_defaultcontroller = (string) $controller;    return $this;  }  public function getdefaultcontrollername()  {    return $this->_defaultcontroller;  }  public function setdefaultaction($action)  {    $this->_defaultaction = (string) $action;    return $this;  }  public function getdefaultaction()  {    return $this->_defaultaction;  }  public function setdefaultmodule($module)  {    $this->_defaultmodule = (string) $module;    return $this;  }  public function getdefaultmodule()  {    return $this->_defaultmodule;  }}
zend_controller_dispatcher_standard
zendframework继承抽象类zend_controller_dispatcher_abstract,定义了zend_controller_dispatcher_standard。zend_controller_dispatcher_standard是zendframework提供的基本的分发器,完成了分发功能。
_curmodule = $this->getdefaultmodule();  }  public function addcontrollerdirectory($path, $module = null)  {    if (null === $module) {      $module = $this->_defaultmodule;    }    $module = (string) $module;    $path  = rtrim((string) $path, '/\\');    $this->_controllerdirectory[$module] = $path;    return $this;  }  public function setcontrollerdirectory($directory, $module = null)  {    $this->_controllerdirectory = array();    if (is_string($directory)) {      $this->addcontrollerdirectory($directory, $module);    } elseif (is_array($directory)) {      foreach ((array) $directory as $module => $path) {        $this->addcontrollerdirectory($path, $module);      }    } else {      require_once 'zend/controller/exception.php';      throw new zend_controller_exception('controller directory spec must be either a string or an array');    }    return $this;  }  public function getcontrollerdirectory($module = null)  {    if (null === $module) {      return $this->_controllerdirectory;    }    $module = (string) $module;    if (array_key_exists($module, $this->_controllerdirectory)) {      return $this->_controllerdirectory[$module];    }    return null;  }  public function removecontrollerdirectory($module)  {    $module = (string) $module;    if (array_key_exists($module, $this->_controllerdirectory)) {      unset($this->_controllerdirectory[$module]);      return true;    }    return false;  }  public function formatmodulename($unformatted)  {    if (($this->_defaultmodule == $unformatted) && !$this->getparam('prefixdefaultmodule')) {      return $unformatted;    }    return ucfirst($this->_formatname($unformatted));  }  public function formatclassname($modulename, $classname)  {    return $this->formatmodulename($modulename) . '_' . $classname;  }  public function classtofilename($class)  {    return str_replace('_', directory_separator, $class) . '.php';  }  public function isdispatchable(zend_controller_request_abstract $request)  {    $classname = $this->getcontrollerclass($request);    if (!$classname) {      return false;    }    $finalclass = $classname;    if (($this->_defaultmodule != $this->_curmodule)      || $this->getparam('prefixdefaultmodule'))    {      $finalclass = $this->formatclassname($this->_curmodule, $classname);    }    if (class_exists($finalclass, false)) {      return true;    }    $filespec  = $this->classtofilename($classname);    $dispatchdir = $this->getdispatchdirectory();    $test    = $dispatchdir . directory_separator . $filespec;    return zend_loader::isreadable($test);  }  public function dispatch(zend_controller_request_abstract $request, zend_controller_response_abstract $response)  {    $this->setresponse($response);    /**     * get controller class     */    if (!$this->isdispatchable($request)) {      $controller = $request->getcontrollername();      if (!$this->getparam('usedefaultcontrolleralways') && !empty($controller)) {        require_once 'zend/controller/dispatcher/exception.php';        throw new zend_controller_dispatcher_exception('invalid controller specified (' . $request->getcontrollername() . ')');      }      $classname = $this->getdefaultcontrollerclass($request);    } else {      $classname = $this->getcontrollerclass($request);      if (!$classname) {        $classname = $this->getdefaultcontrollerclass($request);      }    }    /**     * load the controller class file     */    $classname = $this->loadclass($classname);    /**     * instantiate controller with request, response, and invocation     * arguments; throw exception if it's not an action controller     */    $controller = new $classname($request, $this->getresponse(), $this->getparams());    if (!($controller instanceof zend_controller_action_interface) &&      !($controller instanceof zend_controller_action)) {      require_once 'zend/controller/dispatcher/exception.php';      throw new zend_controller_dispatcher_exception(        'controller ' . $classname . ' is not an instance of zend_controller_action_interface'      );    }    /**     * retrieve the action name     */    $action = $this->getactionmethod($request);    /**     * dispatch the method call     */    $request->setdispatched(true);    // by default, buffer output    $disableob = $this->getparam('disableoutputbuffering');    $oblevel  = ob_get_level();    if (empty($disableob)) {      ob_start();    }    try {      $controller->dispatch($action);    } catch (exception $e) {      // clean output buffer on error      $curoblevel = ob_get_level();      if ($curoblevel > $oblevel) {        do {          ob_get_clean();          $curoblevel = ob_get_level();        } while ($curoblevel > $oblevel);      }      throw $e;    }    if (empty($disableob)) {      $content = ob_get_clean();      $response->appendbody($content);    }    // destroy the page controller instance and reflection objects    $controller = null;  }  public function loadclass($classname)  {    $finalclass = $classname;    if (($this->_defaultmodule != $this->_curmodule)      || $this->getparam('prefixdefaultmodule'))    {      $finalclass = $this->formatclassname($this->_curmodule, $classname);    }    if (class_exists($finalclass, false)) {      return $finalclass;    }    $dispatchdir = $this->getdispatchdirectory();    $loadfile  = $dispatchdir . directory_separator . $this->classtofilename($classname);    if (zend_loader::isreadable($loadfile)) {      include_once $loadfile;    } else {      require_once 'zend/controller/dispatcher/exception.php';      throw new zend_controller_dispatcher_exception('cannot load controller class ' . $classname . ' from file ' . $loadfile . ');    }    if (!class_exists($finalclass, false)) {      require_once 'zend/controller/dispatcher/exception.php';      throw new zend_controller_dispatcher_exception('invalid controller class (' . $finalclass . ')');    }    return $finalclass;  }  public function getcontrollerclass(zend_controller_request_abstract $request)  {    $controllername = $request->getcontrollername();    if (empty($controllername)) {      if (!$this->getparam('usedefaultcontrolleralways')) {        return false;      }      $controllername = $this->getdefaultcontrollername();      $request->setcontrollername($controllername);    }    $classname = $this->formatcontrollername($controllername);    $controllerdirs   = $this->getcontrollerdirectory();    $module = $request->getmodulename();    if ($this->isvalidmodule($module)) {      $this->_curmodule  = $module;      $this->_curdirectory = $controllerdirs[$module];    } elseif ($this->isvalidmodule($this->_defaultmodule)) {      $request->setmodulename($this->_defaultmodule);      $this->_curmodule  = $this->_defaultmodule;      $this->_curdirectory = $controllerdirs[$this->_defaultmodule];    } else {      require_once 'zend/controller/exception.php';      throw new zend_controller_exception('no default module defined for this application');    }    return $classname;  }  public function isvalidmodule($module)  {    if (!is_string($module)) {      return false;    }    $module    = strtolower($module);    $controllerdir = $this->getcontrollerdirectory();    foreach (array_keys($controllerdir) as $modulename) {      if ($module == strtolower($modulename)) {        return true;      }    }    return false;  }  public function getdefaultcontrollerclass(zend_controller_request_abstract $request)  {    $controller = $this->getdefaultcontrollername();    $default  = $this->formatcontrollername($controller);    $request->setcontrollername($controller)        ->setactionname(null);    $module       = $request->getmodulename();    $controllerdirs   = $this->getcontrollerdirectory();    $this->_curmodule  = $this->_defaultmodule;    $this->_curdirectory = $controllerdirs[$this->_defaultmodule];    if ($this->isvalidmodule($module)) {      $found = false;      if (class_exists($default, false)) {        $found = true;      } else {        $moduledir = $controllerdirs[$module];        $filespec = $moduledir . directory_separator . $this->classtofilename($default);        if (zend_loader::isreadable($filespec)) {          $found = true;          $this->_curdirectory = $moduledir;        }      }      if ($found) {        $request->setmodulename($module);        $this->_curmodule  = $this->formatmodulename($module);      }    } else {      $request->setmodulename($this->_defaultmodule);    }    return $default;  }  public function getdispatchdirectory()  {    return $this->_curdirectory;  }  public function getactionmethod(zend_controller_request_abstract $request)  {    $action = $request->getactionname();    if (empty($action)) {      $action = $this->getdefaultaction();      $request->setactionname($action);    }    return $this->formatactionname($action);  }}
前端控制器和分发器
_plugins = new zend_controller_plugin_broker();  }  private function __clone()  {  }  public static function getinstance()  {    if (null === self::$_instance) {      self::$_instance = new self();    }    return self::$_instance;  }  public function resetinstance()  {    $reflection = new reflectionobject($this);    foreach ($reflection->getproperties() as $property) {      $name = $property->getname();      switch ($name) {        case '_instance':          break;        case '_controllerdir':        case '_invokeparams':          $this->{$name} = array();          break;        case '_plugins':          $this->{$name} = new zend_controller_plugin_broker();          break;        case '_throwexceptions':        case '_returnresponse':          $this->{$name} = false;          break;        case '_modulecontrollerdirectoryname':          $this->{$name} = 'controllers';          break;        default:          $this->{$name} = null;          break;      }    }    zend_controller_action_helperbroker::resethelpers();  }  public static function run($controllerdirectory)  {    self::getinstance()      ->setcontrollerdirectory($controllerdirectory)      ->dispatch();  }  public function addcontrollerdirectory($directory, $module = null)  {    $this->getdispatcher()->addcontrollerdirectory($directory, $module);    return $this;  }  public function setcontrollerdirectory($directory, $module = null)  {    $this->getdispatcher()->setcontrollerdirectory($directory, $module);    return $this;  }  public function getcontrollerdirectory($name = null)  {    return $this->getdispatcher()->getcontrollerdirectory($name);  }  public function removecontrollerdirectory($module)  {    return $this->getdispatcher()->removecontrollerdirectory($module);  }  public function addmoduledirectory($path)  {    try{      $dir = new directoryiterator($path);    } catch(exception $e) {      require_once 'zend/controller/exception.php';      throw new zend_controller_exception(directory $path not readable, 0, $e);    }    foreach ($dir as $file) {      if ($file->isdot() || !$file->isdir()) {        continue;      }      $module  = $file->getfilename();      // don't use sccs directories as modules      if (preg_match('/^[^a-z]/i', $module) || ('cvs' == $module)) {        continue;      }      $moduledir = $file->getpathname() . directory_separator . $this->getmodulecontrollerdirectoryname();      $this->addcontrollerdirectory($moduledir, $module);    }    return $this;  }  public function getmoduledirectory($module = null)  {    if (null === $module) {      $request = $this->getrequest();      if (null !== $request) {        $module = $this->getrequest()->getmodulename();      }      if (empty($module)) {        $module = $this->getdispatcher()->getdefaultmodule();      }    }    $controllerdir = $this->getcontrollerdirectory($module);    if ((null === $controllerdir) || !is_string($controllerdir)) {      return null;    }    return dirname($controllerdir);  }  public function setmodulecontrollerdirectoryname($name = 'controllers')  {    $this->_modulecontrollerdirectoryname = (string) $name;    return $this;  }  public function getmodulecontrollerdirectoryname()  {    return $this->_modulecontrollerdirectoryname;  }  public function setdefaultcontrollername($controller)  {    $dispatcher = $this->getdispatcher();    $dispatcher->setdefaultcontrollername($controller);    return $this;  }  public function getdefaultcontrollername()  {    return $this->getdispatcher()->getdefaultcontrollername();  }  public function setdefaultaction($action)  {    $dispatcher = $this->getdispatcher();    $dispatcher->setdefaultaction($action);    return $this;  }  public function getdefaultaction()  {    return $this->getdispatcher()->getdefaultaction();  }  public function setdefaultmodule($module)  {    $dispatcher = $this->getdispatcher();    $dispatcher->setdefaultmodule($module);    return $this;  }  public function getdefaultmodule()  {    return $this->getdispatcher()->getdefaultmodule();  }  public function setrequest($request)  {    ...........................    return $this;  }  public function getrequest()  {    return $this->_request;  }  public function setrouter($router)  {    ....................    return $this;  }  public function getrouter()  {    ..................    return $this->_router;  }  public function setbaseurl($base = null)  {    ..............    return $this;  }  public function getbaseurl()  {    return $this->_baseurl;  }  /**   * set the dispatcher object. the dispatcher is responsible for   * taking a zend_controller_dispatcher_token object, instantiating the controller, and   * call the action method of the controller.   *   * @param zend_controller_dispatcher_interface $dispatcher   * @return zend_controller_front   */  public function setdispatcher(zend_controller_dispatcher_interface $dispatcher)  {    $this->_dispatcher = $dispatcher;    return $this;  }  /**   * return the dispatcher object.   *   * @return zend_controller_dispatcher_interface   */  public function getdispatcher()  {    /**     * instantiate the default dispatcher if one was not set.     */    if (!$this->_dispatcher instanceof zend_controller_dispatcher_interface) {      require_once 'zend/controller/dispatcher/standard.php';      $this->_dispatcher = new zend_controller_dispatcher_standard();    }    return $this->_dispatcher;  }  public function setresponse($response)  {..................    return $this;  }  public function getresponse()  {    return $this->_response;  }  public function setparam($name, $value)  {    $name = (string) $name;    $this->_invokeparams[$name] = $value;    return $this;  }  public function setparams(array $params)  {    $this->_invokeparams = array_merge($this->_invokeparams, $params);    return $this;  }  public function getparam($name)  {    if(isset($this->_invokeparams[$name])) {      return $this->_invokeparams[$name];    }    return null;  }  public function getparams()  {    return $this->_invokeparams;  }  public function clearparams($name = null)  {    if (null === $name) {      $this->_invokeparams = array();    } elseif (is_string($name) && isset($this->_invokeparams[$name])) {      unset($this->_invokeparams[$name]);    } elseif (is_array($name)) {      foreach ($name as $key) {        if (is_string($key) && isset($this->_invokeparams[$key])) {          unset($this->_invokeparams[$key]);        }      }    }    return $this;  }  public function registerplugin(zend_controller_plugin_abstract $plugin, $stackindex = null)  {    $this->_plugins->registerplugin($plugin, $stackindex);    return $this;  }  public function unregisterplugin($plugin)  {    $this->_plugins->unregisterplugin($plugin);    return $this;  }  public function hasplugin($class)  {    return $this->_plugins->hasplugin($class);  }  public function getplugin($class)  {    return $this->_plugins->getplugin($class);  }  public function getplugins()  {    return $this->_plugins->getplugins();  }  public function throwexceptions($flag = null)  {    .....................    return $this->_throwexceptions;  }  public function returnresponse($flag = null)  {    ................    return $this->_returnresponse;  }  /**   * dispatch an http request to a controller/action.   *   * @param zend_controller_request_abstract|null $request   * @param zend_controller_response_abstract|null $response   * @return void|zend_controller_response_abstract returns response object if returnresponse() is true   */  public function dispatch(zend_controller_request_abstract $request = null, zend_controller_response_abstract $response = null)  {    if (!$this->getparam('noerrorhandler') && !$this->_plugins->hasplugin('zend_controller_plugin_errorhandler')) {      // register with stack index of 100      require_once 'zend/controller/plugin/errorhandler.php';      $this->_plugins->registerplugin(new zend_controller_plugin_errorhandler(), 100);    }    if (!$this->getparam('noviewrenderer') && !zend_controller_action_helperbroker::hashelper('viewrenderer')) {      require_once 'zend/controller/action/helper/viewrenderer.php';      zend_controller_action_helperbroker::getstack()->offsetset(-80, new zend_controller_action_helper_viewrenderer());    }    /**     * instantiate default request object (http version) if none provided     */    if (null !== $request) {      $this->setrequest($request);    } elseif ((null === $request) && (null === ($request = $this->getrequest()))) {      require_once 'zend/controller/request/http.php';      $request = new zend_controller_request_http();      $this->setrequest($request);    }    /**     * set base url of request object, if available     */    if (is_callable(array($this->_request, 'setbaseurl'))) {      if (null !== $this->_baseurl) {        $this->_request->setbaseurl($this->_baseurl);      }    }    /**     * instantiate default response object (http version) if none provided     */    if (null !== $response) {      $this->setresponse($response);    } elseif ((null === $this->_response) && (null === ($this->_response = $this->getresponse()))) {      require_once 'zend/controller/response/http.php';      $response = new zend_controller_response_http();      $this->setresponse($response);    }    /**     * register request and response objects with plugin broker     */    $this->_plugins       ->setrequest($this->_request)       ->setresponse($this->_response);    /**     * initialize router     */    $router = $this->getrouter();    $router->setparams($this->getparams());    /**     * initialize dispatcher     */    $dispatcher = $this->getdispatcher();    $dispatcher->setparams($this->getparams())          ->setresponse($this->_response);    // begin dispatch    try {      /**       * route request to controller/action, if a router is provided       */      /**      * notify plugins of router startup      */      $this->_plugins->routestartup($this->_request);      try {        $router->route($this->_request);      } catch (exception $e) {        if ($this->throwexceptions()) {          throw $e;        }        $this->_response->setexception($e);      }      /**      * notify plugins of router completion      */      $this->_plugins->routeshutdown($this->_request);      /**       * notify plugins of dispatch loop startup       */      $this->_plugins->dispatchloopstartup($this->_request);      /**       * attempt to dispatch the controller/action. if the $this->_request       * indicates that it needs to be dispatched, move to the next       * action in the request.       */      do {        $this->_request->setdispatched(true);        /**         * notify plugins of dispatch startup         */        $this->_plugins->predispatch($this->_request);        /**         * skip requested action if predispatch() has reset it         */        if (!$this->_request->isdispatched()) {          continue;        }        /**         * dispatch request         */        try {          $dispatcher->dispatch($this->_request, $this->_response);        } catch (exception $e) {          if ($this->throwexceptions()) {            throw $e;          }          $this->_response->setexception($e);        }        /**         * notify plugins of dispatch completion         */        $this->_plugins->postdispatch($this->_request);      } while (!$this->_request->isdispatched());    } catch (exception $e) {      if ($this->throwexceptions()) {        throw $e;      }      $this->_response->setexception($e);    }    /**     * notify plugins of dispatch loop completion     */    try {      $this->_plugins->dispatchloopshutdown();    } catch (exception $e) {      if ($this->throwexceptions()) {        throw $e;      }      $this->_response->setexception($e);    }    if ($this->returnresponse()) {      return $this->_response;    }    $this->_response->sendresponse();  }}
以上对zend_controller_front和zend_controller_dispatcher做了简单的标记,通过分析代码不难看出,基本的运行机制。
分发发生在前端控制器中的一个循环(loop)中。分发之前,前端控制器通过路由请求,找到用户指定的模块、控制器、动作和可选参数。然后进入分发循环,分发请求。
分发器需要大量数据完成任务——它需要知道如何格式化控制器和动作的名称,到哪儿找到控制器类文件,模块名是否有效,以及基于其它可用信息判定请求是否能分发的api。
每次迭代(iteration)过程开始时,在请求对象中设置一个标志指示该动作已分发。如果在动作或者前/后分发(pre/postdispatch)插件重置了该标志,分发循环将继续下去并试图分发新的请求。通过改变请求中的控制器或者动作并重置已分发标志,开发人员可以定制执行一个请求链。
控制这种分发过程的动作控制器方法是_forward();在任意的pre/postdispatch()或者动作中调用该方法,并传入动作、控制器、模块、以及可选的附加参数,就可以进入新的动作。
自定义分发器
zend_controller_dispatcher_interface定义了下列所有分发器需要实现的方法。
不过大多数情况下,只需要简单地扩展抽象类zend_controller_dispatcher_abstract,其中已经定义好了上面的大部分方法。或者扩展zend_controller_dispatcher_standard类,基于标准分发器来修改功能。
需要子类化分发器的可能原因包括:期望在动作控制器中使用不同的类和方法命名模式,或者期望使用不同的分发方式,比如分发到控制器目录下的动作文件,而不是控制器类的动作方法。
更多关于zend相关内容感兴趣的读者可查看本站专题:《zend framework框架入门教程》、《php优秀开发框架总结》、《yii框架入门及常用技巧总结》、《thinkphp入门教程》、《php面向对象程序设计入门教程》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》
希望本文所述对大家php程序设计有所帮助。
您可能感兴趣的文章:zend framework教程之autoloading用法详解zend framework教程之resource autoloading用法实例zend framework教程之mvc框架的controller用法分析zend framework教程之路由功能zend_controller_router详解zend framework教程之zend_controller_plugin插件用法详解zend framework教程之响应对象的封装zend_controller_response实例详解zend framework教程之请求对象的封装zend_controller_request实例详解zend framework教程之动作的基类zend_controller_action详解zend framework教程之前端控制器zend_controller_front用法详解zend framework教程之视图组件zend_view用法详解zend framework教程之loader以及pluginloader用法详解
http://www.bkjia.com/phpjc/1106894.htmlwww.bkjia.comtruehttp://www.bkjia.com/phpjc/1106894.htmltecharticlezend framework教程之分发器zend_controller_dispatcher用法详解,zendframework 本文实例讲述了zend framework教程之分发器zend_controller_dispatcher用法。分享给...
   
 
   