用过亿路PHP的朋友发现,无论是模型类还是逻辑类,辅助类还是工具类,使用所有的类都不需要在配置文件中加载注入,也不需要使用include或者在页面require或者use中,直接使用$app->classname->methodname()即可。这个机制太方便了,刚开始用的人都会有点不知所措,担心自己是不是做错了什么?我现在告诉你,你没有少做,没有做错。YiluPHP就是这样设计的。让我告诉你YiluPHP是如何做到的。有些人可能想使用spl_autoload_register()函数来完成。spl_autoload_register()函数可以注册任意数量的自动加载器,例如第三方库中的自动加载器。找一个类需要遍历所有的autoloader,效率很低。这不符合易路PHP追求速度的原则。YiluPHP的$app是一个全局变量,是一个名为YiluPHP的类的实例。这个类使用了PHP的魔术方法__get。代码如下:publicfunction__get($name){if(isset($this->helper[$name])){return$this->helper[$name];}$fun=$this->autoload_class;$class_name=$fun($name);取消设置($乐趣);如果($class_name!==false){$this->helper[$name]=new$class_name;返回$this->helper[$name];}thrownewException($this->lang('class_not_found').$name);}当使用$app->classname->methodname()时,会先从$app的helper属性中检查是否有对应的类实例(helper属性是一个容器,里面包含了所有拥有的类实例已经使用过,所以第二次使用同一个类时,不会再去查找文件或实例化,直接从helper容器返回,helper容器的设计也是易路PHP运行的原因之一fast.)如果找不到对应的类实例,就会调用自己的autoload_class()函数去寻找文件。autoload_class()函数赋值给$app的一个属性,它的实现在$app的构造函数__construct()中,publicfunction__construct(){$this->autoload_class=function($class_name){$file=$GLOBALS['project_root'].'helper/'.$class_name.'.php';if(file_exists($file)){//helperclass文件的文件名、类名、app中的调用方法需要保持一致require_once($file);返回$类名;}//对驼峰命名法使用下划线split$path=preg_replace('/(?<=[a-z])([A-Z])/','_$1',$class_name);$path=explode('_',$path,2);$path=$path[0].'/'.$class_name;$file=$GLOBALS['project_root'].$path.'.php';if(file_exists($file)){//class文件的文件名,类名和app中的调用方法需要一致require_once($file);返回$类名;}//支持类的别名GLOBALS['config']['helper_alias'][$class_name];$file=$GLOBALS['project_root'].'helper/'.$real_class_name.'.php';如果(文件存在($文件)){require_once($文件);返回$real_class_name;}//用下划线分隔驼峰命名法$path=preg_replace('/(?<=[a-z])([A-Z])/','_$1',$real_class_name);$path=explode('_',$path,2);$path=$path[0].'/'.$real_class_name;$file=$GLOBALS['project_root'].$path.'.PHP';如果(file_exists($file)){require_once($file);返回$real_class_name;}}返回假;};}autoload_class()函数首先去helper目录下寻找class文件,如果没有找到,则根据类名前缀的单词去对应目录下寻找class文件(根据查找的过程类的别名也省略),如果找不到则抛出“找不到类”的异常。其实最早作者是打算把所有的class文件都放在helper目录下,就是为了减少程序的执行过程,提高框架的运行速度。但是考虑到以下两个原因,还是决定支持目录存储类别的划分:第一,如果系统功能太多,class文件很多,写代码的时候很难定位到class文件。虽然当系统功能过多时,最好的选择是将大系统拆分成小系统,分别部署,分散压力。但是,很多创业公司很容易因为需求的快速变化而造成文件过多。二、根据不同的功能将class文件存放在不同的目录已经成为几乎所有程序员都有的一种结构化思维习惯,而遵循这种习惯可以让程序员更快的适应易路PHP框架。除了保留子目录存储的习惯外,还有一种命名习惯,也是兼容“下划线字”和“驼峰式”两种命名规则。所以,一个模型类可以这样命名model_user,modelUser也可以这样命名。,可以自动识别。下面是一个类方法被调用的流程图
