当前位置:首页 > CMS教程 > 其它CMS > 列表

PHP的Yii框架中YiiBase入口类的扩展写法示例

发布:smiling 来源: PHP粉丝网  添加日期:2021-07-17 21:02:45 浏览: 评论:0 

这篇文章主要介绍了PHP的Yii框架中YiiBase入口类的扩展写法示例,同时详细讲解了import和autoload这两个YiiBase中的重要方法,需要的朋友可以参考下。

通过yiic.php自动创建一个应用后,入口文件初始代码如下:

  1. <?php 
  2. // change the following paths if necessary 
  3. $yii=dirname(__FILE__).'/../yii/framework/yii.php'
  4. $config=dirname(__FILE__).'/protected/config/main.php'
  5. // remove the following lines when in production mode 
  6. defined('YII_DEBUG'or define('YII_DEBUG',true); 
  7. // specify how many levels of call stack should be shown in each log message 
  8. defined('YII_TRACE_LEVEL'or define('YII_TRACE_LEVEL',3); 
  9. require_once($yii); 
  10. Yii::createWebApplication($config)->run(); 

其中第三行引入了一个yii.php的文件,这个可以在yii核心目录里的framework/下找到,这个文件中定义了一个Yii类,并且继承了YiiBase类。

代码如下:

  1. require(dirname(__FILE__).'/YiiBase.php'); 
  2.    
  3. /** 
  4.  * Yii is a helper class serving common framework functionalities. 
  5.  * 
  6.  * It encapsulates {@link YiiBase} which provides the actual implementation. 
  7.  * By writing your own Yii class, you can customize some functionalities of YiiBase. 
  8.  * 
  9.  * @author Qiang Xue <qiang.xue@gmail.com> 
  10.  * @package system 
  11.  * @since 1.0 
  12.  */ 
  13. class Yii extends YiiBase 

Yii::createWebApplication

这个方法实际上是在YiiBase父类中定义的,所以,Yii为我们预留了扩展的可能。我们只需要在yii.php中添加我们想要扩展的方法即可,在项目中直接使用 Yii::方法名() 调用。

为了将项目代码和核心目录完全分离,我个人觉得在项目目录下使用另外一个yii.php来替代从核心目录中包含yii.php更加好。

这里我用了更加极端的方法,我直接将yii这个类定义在了入口文件,并扩展了一个全局工厂函数 instance()方法,请看代码:

  1. <?php 
  2. // change the following paths if necessary 
  3. $yii=dirname(__FILE__).'/../yii/framework/YiiBase.php'
  4. $config=dirname(__FILE__).'/protected/config/main.php'
  5. // remove the following lines when in production mode 
  6. defined('YII_DEBUG'or define('YII_DEBUG',true); 
  7. // specify how many levels of call stack should be shown in each log message 
  8. defined('YII_TRACE_LEVEL'or define('YII_TRACE_LEVEL',3); 
  9. require_once($yii); 
  10. //扩展基类 
  11. class Yii extends YiiBase{ 
  12.   /** 
  13.    * 全局扩展方法:工厂函数 
  14.    * @param type $alias 类库别名 
  15.    */ 
  16.   static function instance($alias){ 
  17.     static $_class_ = array(); 
  18.     $key = md5($alias); 
  19.     if(!isset($_class_[$key])){ 
  20.       $_class_[$key] = self::createComponent($alias); 
  21.     } 
  22.     return $_class_[$key]; 
  23.   } 
  24. Yii::createWebApplication($config)->run(); 

这个类是在最后一行Yii::createWebApplication()之前定义的,以保证Yii类能正常使用(不要把这个类放在文件末尾,会出错。)

在项目中任何地方,使用$obj = Yii::instance($alias);去实例化一个类,并且是单例模式。

YiiBase中的两个比较重要的方法 (import,autoload)

然后看看YiiBase中的import方法就知道这些静态变量是干嘛用的了:

  1. /* Yii::import() 
  2. * $alias: 要导入的类名或路径 
  3. * $forceInclude false:只导入不include类文件,true则导入并include类文件 
  4. */ 
  5.  public static function import($alias$forceInclude = false){   
  6.  //Yii把所有的依赖放入到这个全局的$_imports数组中,名字不能重复 
  7.  //如果当前依赖已经被引入过了,那么直接返回 
  8.  if (isset(self::$_imports[$alias])) {     
  9.     return self::$_imports[$alias];   
  10.   }   
  11.  //class_exists和interface_exists方法的第二个参数的值为false表示不autoload  
  12.  if (class_exists($alias, false) || interface_exists($alias, false)) {     
  13.    return self::$_imports[$alias] = $alias;   
  14.  }   
  15.  //如果传进来的是一个php5.3版本的命名空间格式的类(例如:\a\b\c.php) 
  16.  if (($pos = strrpos($alias'\\')) !== false) {     
  17.   //$namespace = a.b 
  18.   $namespace = str_replace('\\', '.', ltrim(substr($alias, 0, $pos), '\\'));  
  19.   //判断a.b这个路径是否存在,或者a.b只是alias里面的一个键,调用该方法返回这个键对应的值,比如'email' => realpath(__DIR__ . '/../vendor/cornernote/yii-email-module/email') 
  20.   if (($path = self::getPathOfAlias($namespace)) !== false) {    
  21.     $classFile = $path . DIRECTORY_SEPARATOR . substr($alias$pos + 1) . '.php';        
  22.     if ($forceInclude) {         
  23.      if (is_file($classFile)) {           
  24.        require($classFile);         
  25.       } else {           
  26.       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('{alias}' => $alias)));         
  27.      }         
  28.      self::$_imports[$alias] = $alias;       
  29.      } else {         
  30.      self::$classMap[$alias] = $classFile;       
  31.     }       
  32.     return $alias;     
  33.   } else {       
  34. // try to autoload the class with an autoloader       
  35.   if (class_exists($alias, true)) {         
  36.     return self::$_imports[$alias] = $alias;       
  37.   } else {         
  38.     throw new CException(Yii::t('yii''Alias "{alias}" is invalid. Make sure it points to an existing directory or file.',          array('{alias}' => $namespace)));       
  39.   }     
  40.   }   
  41.  }   
  42. if (($pos = strrpos($alias'.')) === false) // a simple class name  
  43.  {     
  44.   // try to autoload the class with an autoloader if $forceInclude is true     
  45.   if ($forceInclude && (Yii::autoload($alias, true) || class_exists($alias, true))) {       
  46.    self::$_imports[$alias] = $alias;     
  47.    }     
  48.   return $alias;   
  49.  }   
  50.  $className = (string)substr($alias$pos + 1);   
  51.  
  52.  $isClass = $className !== '*';   
  53.  if ($isClass && (class_exists($className, false) || interface_exists($className, false))) {     
  54.   return self::$_imports[$alias] = $className;   
  55.  }   
  56.  if (($path = self::getPathOfAlias($alias)) !== false) {     
  57.    if ($isClass) {       
  58.       if ($forceInclude) {         
  59.          if (is_file($path . '.php')) {           
  60.              require($path . '.php');         
  61.          } else {           
  62.              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('{alias}' => $alias)));         
  63.              }         
  64.         self::$_imports[$alias] = $className;       
  65.      } else {         
  66.         self::$classMap[$className] = $path . '.php';       
  67.      }       
  68.       return $className;     
  69.     }  
  70.     // $alias是'system.web.*'这样的已*结尾的路径,将路径加到include_path中 
  71.     else // a directory     
  72.      {       
  73.        if (self::$_includePaths === null) {     
  74.           self::$_includePaths = array_unique(explode(PATH_SEPARATOR, get_include_path()));   
  75.            if (($pos = array_search('.', self::$_includePaths, true)) !== false) {           
  76.         unset(self::$_includePaths[$pos]);         
  77.       }       
  78.     }       
  79.     array_unshift(self::$_includePaths$path);       
  80.     if (self::$enableIncludePath && set_include_path('.' . PATH_SEPARATOR . implode(PATH_SEPARATOR, self::$_includePaths)) === false) {         
  81.      self::$enableIncludePath = false;       
  82.      }       
  83.      return self::$_imports[$alias] = $path;     
  84.     }   
  85.   } else {     
  86.     throw new CException(Yii::t('yii''Alias "{alias}" is invalid. Make sure it points to an existing directory or file.',      array('{alias}' => $alias)));   
  87.     } 
  88.  } 

是的,上面这个方法最后就把要加载的东西都放到$_imports,$_includePaths中去了,这就是Yii的import方法,好的,接下来我们看看autoload方法:

  1. public static function autoload($className$classMapOnly = false){  // use include so that the error PHP file may appear   
  2. if (isset(self::$classMap[$className])) {        
  3.   include(self::$classMap[$className]);   
  4. elseif (isset(self::$_coreClasses[$className])) {     
  5.   include(YII_PATH . self::$_coreClasses[$className]);   
  6. elseif ($classMapOnly) {     
  7.   return false;   
  8. else {     
  9.  // include class file relying on include_path     
  10.     if (strpos($className'\\') === false)  
  11.     // class without namespace     
  12.     {       
  13.       if (self::$enableIncludePath === false) {         
  14.          foreach (self::$_includePaths as $path) {               
  15.             $classFile = $path . DIRECTORY_SEPARATOR . $className . '.php';           
  16.             if (is_file($classFile)) {        
  17.                include($classFile);             
  18.               if (YII_DEBUG && basename(realpath($classFile)) !== $className . '.php') {               
  19.                 throw new CException(Yii::t('yii''Class name "{class}" does not match class file "{file}".'array(                '{class}' => $className,                '{file}' => $classFile,              )));             
  20.               }             
  21.               break;           
  22.            }         
  23.        }       
  24.    } else {         
  25.       include($className . '.php');       
  26.        }     
  27.  } else // class name with namespace in PHP 5.3     
  28.    {       
  29.      $namespace = str_replace('\\', '.', ltrim($className, '\\'));     
  30.      if (($path = self::getPathOfAlias($namespace)) !== false) {   
  31.       include($path . '.php');       
  32.      } else {         
  33.       return false;       
  34.      }     
  35.    }     
  36.    return class_exists($className, false) || interface_exists($className, false);    }    return true;} 

config文件中的 import 项里的类或路径在脚本启动中会被自动导入,用户应用里个别类需要引入的类可以在类定义前加入 Yii::import() 语句。

Tags: Yii框架 YiiBase

分享到: