转载请注明:TheViperhttp://www.cnblogs.com/TheViper/
本文将对yii中的mvc,路由器,filter,组件机制等最主要的部分进行自己的一点浅析,力求说明自己做一个php mvc不是那么的遥不可及,其实是很简单的。
源码基于yii 1.13,为了方便说明,我对其进行了大量的裁剪,不过还是让他保有上面的那些最重要的功能。裁剪下来,其实没有几个文件了,而且每个文件代码最多100多行,避免因为代码太多而懒得看。
所谓的mvc都是让所有请求从一个地方进去,通过对请求,配置的解析,分发到对应的类方法中。
首先当然是入口文件,index.php.
1 <?php2 $app = "app";3 $yii = dirname ( __FILE__ ) . '/framework/yii.php';4 $config = dirname ( __FILE__ ) . '/app/PRotected/config/main.php';//载入配置5 require_once ($yii);6 Yii::createWebapplication ( $config )->run ();
引入yii.php
1 <?php2 define ( "VIEWS_DIR", "$app/protected/views/" );3 define ( "CONTROLLERS_DIR", "$app/protected/controllers/" );4 require(dirname(__FILE__).'/YiiBase.php');5 class Yii extends YiiBase6 {7 }
原来yii是个空的类啊,去看YiiBase.
1 <?php 2 defined ( 'YII_PATH' ) or define ( 'YII_PATH', dirname ( __FILE__ ) ); 3 class YiiBase { 4 public static $classMap = array (); 5 public static $enableIncludePath = true; 6 private static $_aliases = array ( 7 'system' => YII_PATH 8 ); // alias => path 9 private static $_imports = array (); // alias => class name or directory 10 private static $_includePaths; // list of include paths 11 private static $_app; 12 private static $_logger; 13 public static function createWebApplication($config = null) { 14 return self::createApplication ( 'CWebApplication', $config ); 15 } 16 public static function createApplication($class, $config = null) { 17 return new $class ( $config ); 18 } 19 public static function app() { 20 return self::$_app; 21 } 22 //别名路径 23 public static function getPathOfAlias($alias) { 24 if (isset ( self::$_aliases [$alias] )) 25 return self::$_aliases [$alias]; 26 elseif (($pos = strpos ( $alias, '.' )) !== false) { 27 $rootAlias = substr ( $alias, 0, $pos ); 28 if (isset ( self::$_aliases [$rootAlias] )) 29 return self::$_aliases [$alias] = rtrim ( self::$_aliases [$rootAlias] . DIRECTORY_SEPARATOR . str_replace ( '.', DIRECTORY_SEPARATOR, substr ( $alias, $pos + 1 ) ), '*' . DIRECTORY_SEPARATOR ); 30 } 31 return false; 32 } 33 public static function setPathOfAlias($alias, $path) { 34 if (empty ( $path )) 35 unset ( self::$_aliases [$alias] ); 36 else 37 self::$_aliases [$alias] = rtrim ( $path, '\\/' ); 38 } 39 public static function setApplication($app) { 40 if (self::$_app === null || $app === null) 41 self::$_app = $app; 42 } 43 public static function import($alias, $forceInclude = false) { 44 if (isset ( self::$_imports [$alias] )) // previously imported 45 return self::$_imports [$alias]; 46 47 if (class_exists ( $alias, false ) || interface_exists ( $alias, false )) 48 return self::$_imports [$alias] = $alias; 49 if (($pos = strrpos ( $alias, '.' )) === false) // a simple class name 50 { 51 // try to autoload the class with an autoloader if $forceInclude is true 52 if ($forceInclude && (Yii::autoload ( $alias, true ) || class_exists ( $alias, true ))) 53 self::$_imports [$alias] = $alias; 54 return $alias; 55 } 56 57 $className = ( string ) substr ( $alias, $pos + 1 ); 58 $isClass = $className !== '*'; 59 60 if ($isClass && (class_exists ( $className, false ) || interface_exists ( $className, false ))) 61 return self::$_imports [$alias] = $className; 62 63 if (($path = self::getPathOfAlias ( $alias )) !== false) { 64 if ($isClass) { 65 if ($forceInclude) { 66 if (is_file ( $path . '.php' )) 67 require ($path . '.php'); 68 else 69 throw new CException ( Yii::t ( 'yii', 'Alias "{alias}" is invalid. Make sure it points to an existing PHP file and the file is readable.', array ( 70 '{alias}' => $alias 71 ) ) ); 72 self::$_imports [$alias] = $className; 73 } else 74 self::$classMap [$className] = $path . '.php'; 75 return $className; 76 } else // a directory 77 { 78 if (self::$_includePaths === null) { 79 self::$_includePaths = array_unique ( explode ( PATH_SEPARATOR, get_include_path () ) ); 80 if (($pos = array_search ( '.', self::$_includePaths, true )) !== false) 81 unset ( self::$_includePaths [$pos] ); 82 } 83 84 array_unshift ( self::$_includePaths, $path ); 85 86 if (self::$enableIncludePath && set_include_path ( '.' . PATH_SEPARATOR . implode ( PATH_SEPARATOR, self::$_includePaths ) ) === false) 87 self::$enableIncludePath = false; 88 89 return self::$_imports [$alias] = $path; 90 } 91 } 92 } 93 //创建组件实例 94 public static function createComponent($config) { 95 if (is_string ( $config )) { 96 $type = $config; 97 $config = array (); 98 } elseif (isset ( $config ['class'] )) { 99 $type = $config ['class'];100 unset ( $config ['class'] );101 }102 if (! class_exists ( $type, false )) {103 $type = Yii::import ( $type, true );104 }105 if (($n = func_num_args ()) > 1) {106 $args = func_get_args ();107 if ($n === 2)108 $object = new $type ( $args [1] );109 elseif ($n === 3)110 $object = new $type ( $args [1], $args [2] );111 elseif ($n === 4)112 $object = new $type ( $args [1], $args [2], $args [3] );113 else {114 unset ( $args [0] );115 $class = new ReflectionClass ( $type );116 // Note: ReflectionClass::newInstanceArgs() is available for PHP 5.1.3+117 // $object=$class->newInstanceArgs($args);118 $object = call_user_func_array ( array (119 $class,120 'newInstance' 121 ), $args );122 }123 } else124 $object = new $type ();125 foreach ( $config as $key => $value )126 $object->$key = $value;127 128 return $object;129 }130 //按需加载相应的php131 public static function autoload($className) {132 include self::$_coreClasses [$className];133 }134 private static $_coreClasses = array (135 'CApplication' => '/base/CApplication.php',136 'CModule' => '/base/CModule.php',137 'CWebApplication' => '/base/CWebApplication.php',138 'CUrlManager' => 'CUrlManager.php',139 'CComponent' => '/base/CComponent.php'140 , 'CUrlRule' => 'CUrlRule.php',141 'CController' => 'CController.php',142 'CInlineAction' => '/actions/CInlineAction.php',143 'CAction' => '/actions/CAction.php',144 'CFilterChain' => '/filters/CFilterChain.php',145 'CFilter' => '/filters/CFilter.php',146 'CList' => '/collections/CList.php',147 'CHttpRequest' => 'CHttpRequest.php',148 'CDb' => 'CDb.php',149 'CInlineFilter' => 'filters/CInlineFilter.php' 150 );151 }152 153 spl_autoload_register ( array (154 'YiiBase',155 'autoload' 156 ) );
看似很多,其实就三个地方注意下就可以了
1.spl_autoload_register,用这个就可以实现传说中的按需加载相应的php了,坑爹啊。
2.createComponent($config)这个