程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> PHP綜合 >> PHP的Yii框架中YiiBase入口類的擴展寫法示例

PHP的Yii框架中YiiBase入口類的擴展寫法示例

編輯:PHP綜合

通過yiic.php自動創建一個應用後,入口文件初始代碼如下:

<?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 <[email protected]>
 * @package system
 * @since 1.0
 */
class Yii extends YiiBase
{
}

Yii::createWebApplication

這個方法實際上是在YiiBase父類中定義的,所以,Yii為我們預留了擴展的可能。我們只需要在yii.php中添加我們想要擴展的方法即可,在項目中直接使用 Yii::方法名() 調用。
為了將項目代碼和核心目錄完全分離,我個人覺得在項目目錄下使用另外一個yii.php來替代從核心目錄中包含yii.php更加好。

這裡我用了更加極端的方法,我直接將yii這個類定義在了入口文件,並擴展了一個全局工廠函數 instance()方法,請看代碼:

<?php
// 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;    
    }  
  } 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() 語句。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved