加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

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

发布时间:2022-02-25 17:06:28 所属栏目:PHP教程 来源:互联网
导读:通过yiic.php自动创建一个应用后,入口文件初始代码如下: // change the following paths if necessary $yii=dirname(__FILE__)./../yii/framework/yii.php; $config=dirname(__FILE__)./protected/config/main.php; // remove the following lines when
  通过yiic.php自动创建一个应用后,入口文件初始代码如下:
 
  // change the following paths if necessary
  
  $yii=dirname(__FILE__).'/../yii/framework/yii.php';
  
  $config=dirname(__FILE__).'/protected/config/main.php';
  
  // remove the following lines when in production mode
  
  defined('YII_DEBUG') or define('YII_DEBUG',true);
  
  // specify how many levels of call stack should be shown in each log message
  
  defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);
  
  require_once($yii);
  
  Yii::createWebApplication($config)->run();
  其中第三行引入了一个yii.php的文件,这个可以在yii核心目录里的framework/下找到,这个文件中定义了一个Yii类,并且继承了YiiBase类。
 
  代码如下:
 
  require(dirname(__FILE__).'/YiiBase.php');
  
  /**
  
   * Yii is a helper class serving common framework functionalities.
  
   *
  
   * It encapsulates {@link YiiBase} which provides the actual implementation.
  
   * By writing your own Yii class, you can customize some functionalities of YiiBase.
  
   *
  
   * @author Qiang Xue <qiang.xue@gmail.com>
  
   * @package system
  
   * @since 1.0
  
   */
  
  class Yii extends YiiBase
  
  {
  
  }
  
  </qiang.xue@gmail.com>
  而:
 
  Yii::createWebApplication
 
  这个方法实际上是在YiiBase父类中定义的,所以,Yii为我们预留了扩展的可能。我们只需要在yii.php中添加我们想要扩展的方法即可,在项目中直接使用 Yii::方法名() 调用。
 
  为了将项目代码和核心目录完全分离,我个人觉得在项目目录下使用另外一个yii.php来替代从核心目录中包含yii.php更加好。
 
  这里我用了更加极端的方法,我直接将yii这个类定义在了入口文件,并扩展了一个全局工厂函数 instance()方法,请看代码:
 
  // change the following paths if necessary
  
  $yii=dirname(__FILE__).'/../yii/framework/YiiBase.php';
  
  $config=dirname(__FILE__).'/protected/config/main.php';
  
  // remove the following lines when in production mode
  
  defined('YII_DEBUG') or define('YII_DEBUG',true);
  
  // specify how many levels of call stack should be shown in each log message
  
  defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);
  
  require_once($yii);
  
  //扩展基类
  
  class Yii extends YiiBase{
  
    /**
  
     * 全局扩展方法:工厂函数
  
     * @param type $alias 类库别名
  
     */
  
    static function instance($alias){
  
      static $_class_ = array();
  
      $key = md5($alias);
  
      if(!isset($_class_[$key])){
  
        $_class_[$key] = self::createComponent($alias);
  
      }
  
      return $_class_[$key];
  
    }
  
  }
  
  Yii::createWebApplication($config)->run();
  这个类是在最后一行Yii::createWebApplication()之前定义的,以保证Yii类能正常使用(不要把这个类放在文件末尾,会出错。)
 
  在项目中任何地方,使用$obj = Yii::instance($alias);去实例化一个类,并且是单例模式。
 
  YiiBase中的两个比较重要的方法 (import,autoload)
 
  然后看看YiiBase中的import方法就知道这些静态变量是干嘛用的了:
 
  /* Yii::import()
  
  * $alias: 要导入的类名或路径
  
  * $forceInclude false:只导入不include类文件,true则导入并include类文件
  
  */
  
   public static function import($alias, $forceInclude = false){   
  
   //Yii把所有的依赖放入到这个全局的$_imports数组中,名字不能重复
  
   //如果当前依赖已经被引入过了,那么直接返回
  
   if (isset(self::$_imports[$alias])) {     
  
      return self::$_imports[$alias];   
  
    }   
  
   //class_exists和interface_exists方法的第二个参数的值为false表示不autoload  
  
   if (class_exists($alias, false) || interface_exists($alias, false)) {     
  
     return self::$_imports[$alias] = $alias;   
  
   }   
  
   //如果传进来的是一个php5.3版本的命名空间格式的类(例如:a/b/c.php)
  
   if (($pos = strrpos($alias, '//')) !== false) {     
  
    //$namespace = a.b
  
    $namespace = str_replace('//', '.', ltrim(substr($alias, 0, $pos), '//'));  
  
    //判断a.b这个路径是否存在,或者a.b只是alias里面的一个键,调用该方法返回这个键对应的值,比如'email' => realpath(__DIR__ . '/../vendor/cornernote/yii-email-module/email')
  
    if (($path = self::getPathOfAlias($namespace)) !== false) {    
  
      $classFile = $path . DIRECTORY_SEPARATOR . substr($alias, $pos + 1) . '.php';        
  
      if ($forceInclude) {         
  
       if (is_file($classFile)) {           
  
         require($classFile);         
  
        } else {           
  
        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)));         
  
       }         
  
       self::$_imports[$alias] = $alias;       
  
       } else {         
  
       self::$classMap[$alias] = $classFile;       
  
      }       
  
      return $alias;     
  
    } else {       
  
  // try to autoload the class with an autoloader       
  
    if (class_exists($alias, true)) {         
  
      return self::$_imports[$alias] = $alias;       
  
    } else {         
  
      throw new CException(Yii::t('yii', 'Alias "{alias}" is invalid. Make sure it points to an existing directory or file.',          array('{alias}' => $namespace)));       
  
    }     
  
    }   
  
   }   
  
  if (($pos = strrpos($alias, '.')) === false) // a simple class name  
  
   {     
  
    // try to autoload the class with an autoloader if $forceInclude is true     
  
    if ($forceInclude && (Yii::autoload($alias, true) || class_exists($alias, true))) {       
  
     self::$_imports[$alias] = $alias;     
  
     }     
  
    return $alias;   
  
   }   
  
   $className = (string)substr($alias, $pos + 1);   
  
  
  
   $isClass = $className !== '*';   
  
   if ($isClass && (class_exists($className, false) || interface_exists($className, false))) {     
  
    return self::$_imports[$alias] = $className;   
  
   }   
  
   if (($path = self::getPathOfAlias($alias)) !== false) {     
  
     if ($isClass) {       
  
        if ($forceInclude) {         
  
           if (is_file($path . '.php')) {           
  
               require($path . '.php');         
  
           } else {           
  
               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)));         
  
               }         
  
          self::$_imports[$alias] = $className;       
  
       } else {         
  
          self::$classMap[$className] = $path . '.php';       
  
       }       
  
        return $className;     
  
      }  
  
      // $alias是'system.web.*'这样的已*结尾的路径,将路径加到include_path中
  
      else // a directory     
  
       {       
  
         if (self::$_includePaths === null) {     
  
            self::$_includePaths = array_unique(explode(PATH_SEPARATOR, get_include_path()));   
  
             if (($pos = array_search('.', self::$_includePaths, true)) !== false) {           
  
          unset(self::$_includePaths[$pos]);         
  
        }       
  
      }       
  
      array_unshift(self::$_includePaths, $path);       
  
      if (self::$enableIncludePath && set_include_path('.' . PATH_SEPARATOR . implode(PATH_SEPARATOR, self::$_includePaths)) === false) {         
  
       self::$enableIncludePath = false;       
  
       }       
  
       return self::$_imports[$alias] = $path;     
  //Cuoxin.com
      }   
  
    } else {     
  
      throw new CException(Yii::t('yii', 'Alias "{alias}" is invalid. Make sure it points to an existing directory or file.',      array('{alias}' => $alias)));   
  
      }
  
   }
  是的,上面这个方法最后就把要加载的东西都放到$_imports,$_includePaths中去了。这就是Yii的import方法,好的,接下来我们看看autoload方法:
 
  public static function autoload($className, $classMapOnly = false){  // use include so that the error PHP file may appear   
  
  if (isset(self::$classMap[$className])) {        
  
    include(self::$classMap[$className]);   
  
  } elseif (isset(self::$_coreClasses[$className])) {     
  
    include(YII_PATH . self::$_coreClasses[$className]);   
  
  } elseif ($classMapOnly) {     
  
    return false;   
  
  } else {     
  
   // include class file relying on include_path     
  
      if (strpos($className, '//') === false)  
  
      // class without namespace     
  
      {       
  
        if (self::$enableIncludePath === false) {         
  
           foreach (self::$_includePaths as $path) {               
  
              $classFile = $path . DIRECTORY_SEPARATOR . $className . '.php';           
  
              if (is_file($classFile)) {        
  
                 include($classFile);             
  
                if (YII_DEBUG && basename(realpath($classFile)) !== $className . '.php') {               
  
                  throw new CException(Yii::t('yii', 'Class name "{class}" does not match class file "{file}".', array(                '{class}' => $className,                '{file}' => $classFile,              )));             
  
                }             
  
                break;           
  
             }         
  
         }       
  
     } else {         
  
        include($className . '.php');       
  
         }     
  
   } else // class name with namespace in PHP 5.3     
  
     {       
  
       $namespace = str_replace('//', '.', ltrim($className, '//'));     
  
       if (($path = self::getPathOfAlias($namespace)) !== false) {   
  
        include($path . '.php');       
  
       } else {         
  
        return false;       
  
       }     
  
     }     
  
  return class_exists($className, false) || interface_exists($className, false); } return true;}
  config文件中的 import 项里的类或路径在脚本启动中会被自动导入。用户应用里个别类需要引入的类可以在类定义前加入 Yii::import() 语句。


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

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读