标签:目录 函数 自身 code Once iss mod 逻辑 变量
使用过YiluPHP的人都会发现,不管是模型类还是逻辑类、辅助类还是工具类,使用所有类都不需要在配置文件中设置加载或注入,也不需要在页面中使用 include 或 require 或 use ,直接使用 $app->类名->方法名() 就可以了,这个机制如此方便,刚开始使用的人都会有点不知得措,担心自己是不是做错了什么?我现在告诉你,你没有少做啥,也没有做错啥,YiluPHP就是这样设计的,下面我来告诉你YiluPHP是如何做到的。
有人可能会想使用 spl_autoload_register() 函数就能做到, spl_autoload_register() 函数可以注册任意数量的自动加载器,比如第三方库中的,要找一个类需要遍历所有的自动加载器,效率很低,这不符合YiluPHP追求速度的原则。YiluPHP的 $app 是一个全局变量,是名为YiluPHP的类的实例,这个类使用了php的魔术方法 __get,代码如下:
1 public function __get($name) 2 { 3 if (isset($this->helper[$name])) { 4 return $this->helper[$name]; 5 } 6 $fun = $this->autoload_class; 7 $class_name = $fun($name); 8 unset($fun); 9 if ($class_name!==false){ 10 $this->helper[$name] = new $class_name; 11 return $this->helper[$name]; 12 } 13 throw new Exception($this->lang(‘class_not_found‘).$name); 14 }
当使用 $app->类名->方法名() 时,会先从$app的helper属性中查找是否已经有对应的类实例(helper属性是一个容器,装有所有已经使用过的类实例,所以当同一个类被第二次使用时不会再去查找文件,也不会再做实例化操作,直接从helper容器中返回,helper容器的设计也是YiluPHP运行迅速的原因之一),若在容器找不到对应的类实例,会调用自身的 autoload_class() 函数查找文件,autoload_class() 函数是赋值给$app的一个属性的,它的实现在$app的初始化函数 __construct() 中,
1 public function __construct() 2 { 3 $this->autoload_class = function ($class_name){ 4 $file = $GLOBALS[‘project_root‘].‘helper/‘.$class_name.‘.php‘; 5 if (file_exists($file)) { 6 //helper类文件的文件名、类名、app中的调用方法三者需要一致 7 require_once($file); 8 return $class_name; 9 } 10 11 //将驼峰式的名称用下划线分割 12 $path = preg_replace(‘/(?<=[a-z])([A-Z])/‘, ‘_$1‘, $class_name); 13 $path = explode(‘_‘, $path, 2); 14 $path = $path[0].‘/‘.$class_name; 15 $file = $GLOBALS[‘project_root‘].$path.‘.php‘; 16 if (file_exists($file)) { 17 //类文件的文件名、类名、app中的调用方法三者需要一致 18 require_once($file); 19 return $class_name; 20 } 21 22 //支持给类取别名 23 if(!empty($GLOBALS[‘config‘][‘helper_alias‘]) && array_key_exists($class_name, $GLOBALS[‘config‘][‘helper_alias‘]) ){ 24 $real_class_name = $GLOBALS[‘config‘][‘helper_alias‘][$class_name]; 25 $file = $GLOBALS[‘project_root‘].‘helper/‘.$real_class_name.‘.php‘; 26 if (file_exists($file)) { 27 require_once($file); 28 return $real_class_name; 29 } 30 31 //将驼峰式的名称用下划线分割 32 $path = preg_replace(‘/(?<=[a-z])([A-Z])/‘, ‘_$1‘, $real_class_name); 33 $path = explode(‘_‘, $path, 2); 34 $path = $path[0].‘/‘.$real_class_name; 35 $file = $GLOBALS[‘project_root‘].$path.‘.php‘; 36 if (file_exists($file)) { 37 require_once($file); 38 return $real_class_name; 39 } 40 } 41 return false; 42 }; 43 }
YiluPHP是如何做到不用配置、不用注入就能直接使用所有的类?
标签:目录 函数 自身 code Once iss mod 逻辑 变量
原文地址:https://www.cnblogs.com/yiluphp/p/yiluphp_how_to_autoload_class.html