通过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 <qiang.xue@gmail.com> * @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() 语句。

PHP和Python各有优势,选择应基于项目需求。1.PHP适合web开发,语法简单,执行效率高。2.Python适用于数据科学和机器学习,语法简洁,库丰富。

PHP不是在消亡,而是在不断适应和进化。1)PHP从1994年起经历多次版本迭代,适应新技术趋势。2)目前广泛应用于电子商务、内容管理系统等领域。3)PHP8引入JIT编译器等功能,提升性能和现代化。4)使用OPcache和遵循PSR-12标准可优化性能和代码质量。

PHP的未来将通过适应新技术趋势和引入创新特性来实现:1)适应云计算、容器化和微服务架构,支持Docker和Kubernetes;2)引入JIT编译器和枚举类型,提升性能和数据处理效率;3)持续优化性能和推广最佳实践。

在PHP中,trait适用于需要方法复用但不适合使用继承的情况。1)trait允许在类中复用方法,避免多重继承复杂性。2)使用trait时需注意方法冲突,可通过insteadof和as关键字解决。3)应避免过度使用trait,保持其单一职责,以优化性能和提高代码可维护性。

依赖注入容器(DIC)是一种管理和提供对象依赖关系的工具,用于PHP项目中。DIC的主要好处包括:1.解耦,使组件独立,代码易维护和测试;2.灵活性,易替换或修改依赖关系;3.可测试性,方便注入mock对象进行单元测试。

SplFixedArray在PHP中是一种固定大小的数组,适用于需要高性能和低内存使用量的场景。1)它在创建时需指定大小,避免动态调整带来的开销。2)基于C语言数组,直接操作内存,访问速度快。3)适合大规模数据处理和内存敏感环境,但需谨慎使用,因其大小固定。

PHP通过$\_FILES变量处理文件上传,确保安全性的方法包括:1.检查上传错误,2.验证文件类型和大小,3.防止文件覆盖,4.移动文件到永久存储位置。

JavaScript中处理空值可以使用NullCoalescingOperator(??)和NullCoalescingAssignmentOperator(??=)。1.??返回第一个非null或非undefined的操作数。2.??=将变量赋值为右操作数的值,但前提是该变量为null或undefined。这些操作符简化了代码逻辑,提高了可读性和性能。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

Atom编辑器mac版下载
最流行的的开源编辑器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。

禅工作室 13.0.1
功能强大的PHP集成开发环境

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境