PHP的Yii框架中YiiBase入口类的扩展写法示例
发布:smiling 来源: PHP粉丝网 添加日期:2019-11-17 18:27:40 浏览: 评论:0
通过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;
- //phpfensi.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() 语句。
Tags: Yii框架 YiiBase入口类
相关文章
- ·利用Yii框架实现图片上传(2018-08-06)
- ·详解PHP的Yii框架中组件行为的属性注入和方法注入(2019-11-14)
- ·PHP的Yii框架中移除组件所绑定的行为的方法(2019-11-14)
- ·PHP的Yii框架中行为的定义与绑定方法讲解(2019-11-14)
- ·详解在PHP的Yii框架中使用行为Behaviors的方法(2019-11-14)
- ·深入讲解PHP的Yii框架中的属性(Property)(2019-11-17)
- ·解读PHP的Yii框架中请求与响应的处理流程(2019-11-17)
- ·解析PHP的Yii框架中cookie和session功能的相关操作(2019-11-17)
- ·简要剖析PHP的Yii框架的组件化机制的基本知识(2019-11-17)
- ·深入解析PHP的Yii框架中的event事件机制(2019-11-17)
- ·全面解读PHP的Yii框架中的日志功能(2019-11-17)
推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)