再来看一下 system/app.php 文件,主要是干嘛的:

<?php
/**
 * 应用驱动类
 * @copyright   Copyright(c) 2011
 * @author      yuansir <yuansir@live.cn/yuanxuxu.com>
 * @version     1.0
 */
define('SYSTEM_PATH', dirname(__FILE__));
define('ROOT_PATH',  substr(SYSTEM_PATH, 0,-7));
define('SYS_LIB_PATH', SYSTEM_PATH.'/lib');
define('APP_LIB_PATH', ROOT_PATH.'/lib');
define('SYS_CORE_PATH', SYSTEM_PATH.'/core');
define('CONTROLLER_PATH', ROOT_PATH.'/controller');
define('MODEL_PATH', ROOT_PATH.'/model');
define('VIEW_PATH', ROOT_PATH.'/view');
define('LOG_PATH', ROOT_PATH.'/error/');
final class Application {
        public static $_lib = null;
        public static $_config = null;
        public static function init() {
                self::setAutoLibs();
                require SYS_CORE_PATH.'/model.php';
                require SYS_CORE_PATH.'/controller.php';

        }
        /**
         * 创建应用
         * @access      public
         * @param       array   $config
         */
        public static function run($config){
                self::$_config = $config['system'];
                self::init();
                self::autoload();
                self::$_lib['route']->setUrlType(self::$_config['route']['url_type']);
                $url_array = self::$_lib['route']->getUrlArray();
                self::routeToCm($url_array);
        }
        /**
         * 自动加载类库
         * @access      public
         * @param       array   $_lib
         */
        public static function autoload(){
                foreach (self::$_lib as $key => $value){
                        require (self::$_lib[$key]);
                        $lib = ucfirst($key);
                        self::$_lib[$key] = new $lib;
                }
                //初始化cache
                if(is_object(self::$_lib['cache'])){
                        self::$_lib['cache']->init(
                                ROOT_PATH.'/'.self::$_config['cache']['cache_dir'],
                                self::$_config['cache']['cache_prefix'],
                                self::$_config['cache']['cache_time'],
                                self::$_config['cache']['cache_mode']
                                );
                }
        }
        /**
         * 加载类库
         * @access      public
         * @param       string  $class_name 类库名称
         * @return      object
         */
        public static function newLib($class_name){
                $app_lib = $sys_lib = '';
                $app_lib = APP_LIB_PATH.'/'.self::$_config['lib']['prefix'].'_'.$class_name.'.php';
                $sys_lib = SYS_LIB_PATH.'/lib_'.$class_name.'.php';

                if(file_exists($app_lib)){
                        require ($app_lib);
                        $class_name = ucfirst(self::$_config['lib']['prefix']).ucfirst($class_name);
                        return new $class_name;
                }else if(file_exists($sys_lib)){
                        require ($sys_lib);
                        return self::$_lib['$class_name'] = new $class_name;
                }else{
                        trigger_error('加载 '.$class_name.' 类库不存在');
                }
        }
        /**
         * 自动加载的类库
         * @access      public
         */
        public static function setAutoLibs(){
                self::$_lib = array(
                    'route'              =>      SYS_LIB_PATH.'/lib_route.php',
                    'mysql'              =>      SYS_LIB_PATH.'/lib_mysql.php',
                    'template'           =>      SYS_LIB_PATH.'/lib_template.php',
                    'cache'           =>      SYS_LIB_PATH.'/lib_cache.php',
                    'thumbnail'           =>      SYS_LIB_PATH.'/lib_thumbnail.php'
                );
        }
        /**
         * 根据URL分发到Controller和Model
         * @access      public
         * @param       array   $url_array
         */
        public static function routeToCm($url_array = array()){
                $app = '';
                $controller = '';
                $action = '';
                $model = '';
                $params = '';

                if(isset($url_array['app'])){
                        $app = $url_array['app'];
                }

                if(isset($url_array['controller'])){
                        $controller = $model = $url_array['controller'];
                        if($app){
                                $controller_file = CONTROLLER_PATH.'/'.$app.'/'.$controller.'Controller.php';
                                $model_file = MODEL_PATH.'/'.$app.'/'.$model.'Model.php';
                        }else{
                                $controller_file = CONTROLLER_PATH.'/'.$controller.'Controller.php';
                                $model_file = MODEL_PATH.'/'.$model.'Model.php';
                        }
                }else{
                        $controller = $model = self::$_config['route']['default_controller'];
                        if($app){
                                $controller_file = CONTROLLER_PATH.'/'.$app.'/'.self::$_config['route']['default_controller'].'Controller.php';
                                $model_file = MODEL_PATH.'/'.$app.'/'.self::$_config['route']['default_controller'].'Model.php';
                        }else{
                                $controller_file = CONTROLLER_PATH.'/'.self::$_config['route']['default_controller'].'Controller.php';
                                 $model_file = MODEL_PATH.'/'.self::$_config['route']['default_controller'].'Model.php';
                        }
                }
                if(isset($url_array['action'])){
                        $action = $url_array['action'];
                }else{
                        $action = self::$_config['route']['default_action'];
                }

                if(isset($url_array['params'])){
                        $params = $url_array['params'];
                }
                if(file_exists($controller_file)){
                       if (file_exists($model_file)) {
                                require $model_file;
                        }
                        require $controller_file;
                        $controller = $controller.'Controller';
                        $controller = new $controller;
                        if($action){
                                if(method_exists($controller, $action)){
                                        isset($params) ? $controller ->$action($params) : $controller ->$action();
                                }else{
                                        die('控制器方法不存在');
                                }
                        }else{
                                die('控制器方法不存在');
                        }
                }else{
                        die('控制器不存在');
                }
        }

}

我叫它框架驱动类,也许不合适,但是我是这样理解的,它用来启动这个框架,做好一些初始化的工作,下面我来详细分析一下每个方法的功能:

1.首先时定义了一些常量,很明了,不解释了

2.setAutoLibs 这个方法其实就是设定那些是系统启动时自动加载的类库,类库文件都存放在 SYS*LIB_PATH 下面,以 lib*开头的,当然这里你可以根据自己的规则来命名

3.autoload 这个方法就是用来引入你要自动加载的类,然后来实例化,用$_lib 数组来保存类的实例,比如$lib[‘route’]system/lib/lib_route.php 中 lib_route 类的实例

4.newLib 这个方法是用来加载你自定义的类的,自定义类存放在根目录下的 lib 中,但是自定义的类的文件前缀是你自己定义的,看系统配置文件里面有,我定义的是 my,这样我就可以在 lib 目录下新建一个自定义的类了,比如 my_test.php

	<?php
	class MyTest {
        	function __construct() {
       	              echo "my lib test";
        	}
	}

为什么类名这样命名,看下 newLib 方法的实现就知道,其实这些你完全可以定义自己的规则,这个方法会首先去着 lib 下面有没有这个类,如果有就会引入实例化,如果没有就去找系统目录下面的类,有就实例化

5.init 就是一个初始化的方法,里面其实就是加载自动加载的类,以及引入核心控制器和核心模型,这个 2 个核心文件过会我们再来分析 6.run 方法就是启动这个框架的了,里面的最后 2 步很重要,就是获取 URL 然后拆分成一个数组的形似,然后由 routeToCm 来分发到 Controller 和 Model 7.routeToCm 很重要,根据 URL 分发到 Controller 和 Model,这个我们过会来说

在 run 方法中

self::$_lib[‘route’]->setUrlType(self::$_config[‘route’][‘url_type’]); //设置url的类型 $url_array = self::$_lib[‘route’]->getUrlArray();//将url转发成数组 好吧,我们来看下 route 的系统类到底做了什么

<?php
/**
 * URL处理类
 * @copyright   Copyright(c) 2011
 * @author      yuansir <yuansir@live.cn/yuanxuxu.com>
 * @version     1.0
 */
final class Route{
        public $url_query;
        public $url_type;
        public $route_url = array();

        public function __construct() {
                $this->url_query = parse_url($_SERVER['REQUEST_URI']);
        }
        /**
         * 设置URL类型
         * @access      public
         */
        public function setUrlType($url_type = 2){
                if($url_type > 0 && $url_type <3){
                        $this->url_type = $url_type;
                }else{
                        trigger_error("指定的URL模式不存在!");
                }
        }

        /**
         * 获取数组形式的URL
         * @access      public
         */
        public function getUrlArray(){
                $this->makeUrl();
                return $this->route_url;
        }
        /**
         * @access      public
         */
        public function makeUrl(){
                switch ($this->url_type){
                        case 1:
                                $this->querytToArray();
                                break;
                        case 2:
                                $this->pathinfoToArray();
                                break;
                }
        }
        /**
         * 将query形式的URL转化成数组
         * @access      public
         */
        public function querytToArray(){
                $arr = !empty ($this->url_query['query']) ?explode('&', $this->url_query['query']) :array();
                $array = $tmp = array();
                if (count($arr) > 0) {
                        foreach ($arr as $item) {
                                $tmp = explode('=', $item);
                                $array[$tmp[0]] = $tmp[1];
                        }
                        if (isset($array['app'])) {
                                $this->route_url['app'] = $array['app'];
                                unset($array['app']);
                        }
                        if (isset($array['controller'])) {
                                $this->route_url['controller'] = $array['controller'];
                                unset($array['controller']);
                        }
                        if (isset($array['action'])) {
                                $this->route_url['action'] = $array['action'];
                                unset($array['action']);
                        }
                        if(count($array) > 0){
                                $this->route_url['params'] = $array;
                        }
                }else{
                        $this->route_url = array();
                }
        }
        /**
         * 将PATH_INFO的URL形式转化为数组
         * @access      public
         */
        public function pathinfoToArray(){

        }
}

注意 querytToArray 方法,将将 query 形式的 URL 转化成数组,比如原来是localhost/myapp/index.php/app=admin&controller=index&action=edit&id=9&fid=10 这样的 url 就会被转发成如下的数组

array(
        'app'		=>'admin',
	'controller'	=>'index',
	'action'	=>'edit',
	'id'		=>array(
				'id'	=>9,
				'fid'	=>10
			)
)

这下再耐心来看下我写的笨拙的 routeToCm,来通过数组参数来分发到控制器,找到控制器以后还要引用相应的模型,然后就实例化控制器和模型,呵呵,貌似有点成型了。

转载请注明: 转载自Ryan 是菜鸟 | LNMP 技术栈笔记

如果觉得本篇文章对您十分有益,何不 打赏一下

谢谢打赏

本文链接地址: 自己动手写 PHP MVC 框架(二)

知识共享许可协议 本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可