colaphp 学习笔记(四)实战

上一篇展示了colaphp的性能测试,这一篇开始具体的代码分析。

1.修改路由实现controllers目录创建子目录

目的是实现接口控制器和页面控制器按文件夹分离,比如:http://my.letv.com/api/follow/add?cid=1&pid=5566

(1)在创建的应用项目目录下index.php定义APP_DIR

APP_DIR

define('APP_DIR', dirname(__FILE__));
(2)修改Cola.php的setDispatchInfo方法
setDispatchInfo
 1 public function setDispatchInfo($dispatchInfo = null)
 2 {
 3     if (null === $dispatchInfo) {
 4         $router = $this->getRouter();
 5         // add urls to router from config
 6         if (isset(self::$_config['_urls'])) $router->add(self::$_config['_urls'], false);
 7         $pathInfo = $this->getPathInfo();
 8         // add support directory
 9         $pathInfos = explode("/", trim($pathInfo,'/'), 2);
10         if(is_dir(APP_DIR.DS.self::config('_controllersHome').DS.current($pathInfos))){
11             $dispatchInfo = $router->match(next($pathInfos));
12             $dispatchInfo['directory'] = reset($pathInfos);
13         }else{
14             $dispatchInfo = $router->match($pathInfo);
15         }
16     }
17     $this->_dispatchInfo = $dispatchInfo;
18     return $this;
19 }

(3)同时修改dispatch方法

dispatch

 1 public function dispatch()
 2 {
 3     if (!$this->getDispatchInfo()) {
 4         throw new Cola_Exception_Dispatch('No dispatch info found');
 5     }
 6     extract($this->_dispatchInfo);
 7     if (isset($file)) {
 8         if (!file_exists($file)) {
 9             throw new Cola_Exception_Dispatch("Can't find dispatch file:{$file}");
10         }
11         require_once $file;
12     }
13     if (isset($controller)) {
14         if(!empty($directory)){
15             if (!self::loadClass($controller, self::config('_controllersHome').DS.$directory)) {
16                 throw new Cola_Exception_Dispatch("Can't load controller:{$controller}");
17             }
18         }elseif (!self::loadClass($controller, self::config('_controllersHome'))) {
19             throw new Cola_Exception_Dispatch("Can't load controller:{$controller}");
20         }
21             $cls = new $controller();
22     }
23     if (isset($action)) {
24         $func = isset($cls) ? array($cls, $action) : $action;
25         if (!is_callable($func, true)) {
26             throw new Cola_Exception_Dispatch("Can't dispatch action:{$action}");
27         }
28         call_user_func($func);
29     }
30 }

2.ColaPHP运行流程浅析

我们把下载下来的ColaPHP-1.2-ga.zip解压并上传到项目的目录时,会有两个文件夹,cola文件夹是cola的核心文件,demo文件夹是一个示例项目。
(1)当我们请求http://my.letv.com时会请求demo文件夹下的index.php,index.php也是所有动态请求的入口文件。
index.php做了什么呢?php运行错误开启,级别设置,时区设置,加载cola核心Cola.php文件,实例化cola,启动运行,分配请求。

index.php

 1 <?php
 2 error_reporting(E_ALL);
 3 ini_set('display_errors', 'on');
 4 date_default_timezone_set('Asia/Shanghai');
 5 define('APP_DIR', dirname(__FILE__));
 6 require '../Cola/Cola.php';
 7 $cola = Cola::getInstance();
 8  
 9 //$benchmark = new Cola_Com_Benchmark();
10 $cola->boot()->dispatch();
11 //echo "<br />cost:", $benchmark->cost(), 's';

(2)我们来看看cola对象的构建函数:
定义cola核心的Router Model View Controller Com等文件路径,实例化Cola的Config对象赋值给本身的config元素,将核心文件的配置路径返回给本身的_congfig元素。接下来执行本身的registerAutoload方法,一个自动加载类的方法。

__construct

 

 1 protected function __construct()
 2 {
 3     $config['_class'] = array(
 4         'Cola_Router'      => COLA_DIR . '/Router.php',
 5         'Cola_Model'       => COLA_DIR . '/Model.php',
 6         'Cola_View'        => COLA_DIR . '/View.php',
 7         'Cola_Controller'  => COLA_DIR . '/Controller.php',
 8         'Cola_Com'         => COLA_DIR . '/Com.php',
 9         'Cola_Com_Widget'  => COLA_DIR . '/Com/Widget.php',
10         'Cola_Exception'   => COLA_DIR . '/Exception.php'
11     );
12     self::$config = new Cola_Config($config);
13     self::$_config = &self::$config->reference();
14     Cola::registerAutoload();

 

(3)接下cola对象调取了本身的boot方法:
boot 方法做了两件事情,加载应用demo目录下的config.inc.php文件,之后执行了config对象的merge方法,将cola核心文件路径配 置和我们自定的配置比如数据库,缓存,项目的models、controllers、views文件夹名称等配置合并,返回对象本身。

boot

 

 1 public static function boot($config = 'config.inc.php')
 2 {
 3     if (is_string($config)) {
 4         include $config;
 5     }
 6     if (!is_array($config)) {
 7         throw new Exception('Boot config must be an array, if you use config file, the variable should be named $config');
 8     }
 9     self::$config->merge($config);
10     return self::$_instance;
11 }

 

(4)最后执行cola对象的dispatch方法:
dispatch 方法,又做了什么呢?首先执行cola对象的getDispatchInfo,这个方法最终会根据请求地址获取到请求的controllers的目录,名 称,action名称,并赋值给cola对象的dispatchInfo元素,我们打印dispatchInfo会输出类似以下信息:
array(3) { ["controller"]=> string(15) "IndexController" ["action"]=> string(10) "testAction" ["directory"]=> string(3) "api" },对此执行extract函数,键名用于变量名,键值用于变量值。如果有controller加载controller文件,最后执行call_user_func函数执行此controller类的action方法。

dispatch

 1 public function dispatch()
 2 {
 3     if (!$this->getDispatchInfo()) {
 4         throw new Cola_Exception_Dispatch('No dispatch info found');
 5     }
 6     extract($this->_dispatchInfo);
 7     if (isset($file)) {
 8         if (!file_exists($file)) {
 9             throw new Cola_Exception_Dispatch("Can't find dispatch file:{$file}");
10         }
11         require_once $file;
12     }
13     if (isset($controller)) {
14         if(!empty($directory)){
15             if (!self::loadClass($controller, self::config('_controllersHome').DS.$directory)) {
16                 throw new Cola_Exception_Dispatch("Can't load controller:{$controller}");
17             }
18         }elseif (!self::loadClass($controller, self::config('_controllersHome'))) {
19             throw new Cola_Exception_Dispatch("Can't load controller:{$controller}");
20         }
21             $cls = new $controller();
22     }
23     if (isset($action)) {
24         $func = isset($cls) ? array($cls, $action) : $action;
25         if (!is_callable($func, true)) {
26             throw new Cola_Exception_Dispatch("Can't dispatch action:{$action}");
27         }
28         call_user_func($func);
29     }
30 }

(5)最后我们来分析cola.php的自动加载处理:
loadClass 方法有两个参数,类名和路径,如果我们今后开发过程中想要加载某个类,直接执行这个方法,传两个参数的值。这是其一,其二,若$className为空 值,loadClass会加载cola对象的元素_config内的文件,都是colaphp运行的核心文件,在Cola目录下。

loadClass

 1 public static function loadClass($className, $dir = '')
 2 {
 3     if (class_exists($className, false) || interface_exists($className, false)) {
 4         return true;
 5     }
 6     if (isset(self::$_config['_class'][$className])) {
 7         include self::$_config['_class'][$className];
 8         return true;
 9     }
10     if (empty($dir)) {
11         $dir = ('Cola' == substr($className, 0, 4)) ? substr(COLA_DIR, 0, -4) : '';
12     } else {
13         $dir = rtrim($dir,'\\/') . DIRECTORY_SEPARATOR;
14     }
15     $file = str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
16     $classFile = $dir . $file;
17     if (file_exists($classFile)) {
18         include $classFile;
19     }
20     return (class_exists($className, false) || interface_exists($className, false));
21 }

 

 

 

 

 

 

posted @ 2016-09-21 14:21  大鹏666  阅读(898)  评论(0编辑  收藏  举报