使用过YiluPHP的人都会发现,不管是模型类还是逻辑类、辅助类还是工具类,使用所有类都不需要在配置文件中设置加载或注入,也不需要在页面中使用 include 或 require 或 use ,直接使用   $app->类名->方法名()   就可以了,这个机制如此方便,刚开始使用的人都会有点不知得措,担心自己是不是做错了什么?我现在告诉你,你没有少做啥,也没有做错啥,YiluPHP就是这样设计的,下面我来告诉你YiluPHP是如何做到的。

有人可能会想使用 spl_autoload_register() 函数就能做到, spl_autoload_register() 函数可以注册任意数量的自动加载器,比如第三方库中的,要找一个类需要遍历所有的自动加载器,效率很低,这不符合YiluPHP追求速度的原则。YiluPHP的 $app 是一个全局变量,是名为YiluPHP的类的实例,这个类使用了php的魔术方法 __get,代码如下:

     public function __get($name)
{
if (isset($this->helper[$name])) {
return $this->helper[$name];
}
$fun = $this->autoload_class;
$class_name = $fun($name);
unset($fun);
if ($class_name!==false){
$this->helper[$name] = new $class_name;
return $this->helper[$name];
}
throw new Exception($this->lang('class_not_found').$name);
}

当使用   $app->类名->方法名()   时,会先从$app的helper属性中查找是否已经有对应的类实例(helper属性是一个容器,装有所有已经使用过的类实例,所以当同一个类被第二次使用时不会再去查找文件,也不会再做实例化操作,直接从helper容器中返回,helper容器的设计也是YiluPHP运行迅速的原因之一),若在容器找不到对应的类实例,会调用自身的 autoload_class() 函数查找文件,autoload_class() 函数是赋值给$app的一个属性的,它的实现在$app的初始化函数 __construct() 中,

     public function __construct()
{
$this->autoload_class = function ($class_name){
$file = $GLOBALS['project_root'].'helper/'.$class_name.'.php';
if (file_exists($file)) {
//helper类文件的文件名、类名、app中的调用方法三者需要一致
require_once($file);
return $class_name;
} //将驼峰式的名称用下划线分割
$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)) {
//类文件的文件名、类名、app中的调用方法三者需要一致
require_once($file);
return $class_name;
} //支持给类取别名
if(!empty($GLOBALS['config']['helper_alias']) && array_key_exists($class_name, $GLOBALS['config']['helper_alias']) ){
$real_class_name = $GLOBALS['config']['helper_alias'][$class_name];
$file = $GLOBALS['project_root'].'helper/'.$real_class_name.'.php';
if (file_exists($file)) {
require_once($file);
return $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';
if (file_exists($file)) {
require_once($file);
return $real_class_name;
}
}
return false;
};
}
autoload_class() 函数先去helper目录中查找类文件,若找不到,再根据类名前缀单词去相应的目录查找类文件(这中间还省略了根据类的别名查找的流程),再找不到就抛出『找不到类』的异常。其实最早作者打算把所有的类文件都存放在helper目录中的,这是为了减少程序执行流程,从而提升框架的运行速度。但是考虑以下两个方面的原因,还是决定支持划分目录存放类:
第一,如果系统功能太多,类文件也多,写代码时定位类文件困难,虽然当系统功能太多时,最好的选择是将大系统拆分小系统,分别部署分散压力,但是很多创业性公司因需求变化快,也很容易造成文件太多;
第二,按功能不同把类文件存放在不同的目录,已经成为几乎所有程序员结构化思维习惯,顺应这个习惯可以让程序员更快的适应YiluPHP框架。
除了分目录存放的习惯保留了之外,还有命名的习惯也兼容了『下划线连接单词』和『驼峰式』两种命名规则,因此一个model类,即可以这样命名 model_user,也可以这样命名 modelUser,都是可以自动识别的。
下面是一个类的方法被调用的流程图

YiluPHP是如何做到不用配置、不用注入就能直接使用所有的类?的更多相关文章

  1. spring中bean配置和注入场景分析

    bean与spring容器的关系 Bean配置信息定义了Bean的实现及依赖关系,Spring容器根据各种形式的Bean配置信息在容器内部建立Bean定义注册表,然后根据注册表加载.实例化Bean,并 ...

  2. ASP.NET Core 在 JSON 文件中配置依赖注入

    前言 在上一篇文章中写了如何在MVC中配置全局路由前缀,今天给大家介绍一下如何在在 json 文件中配置依赖注入. 在以前的 ASP.NET 4+ (MVC,Web Api,Owin,SingalR等 ...

  3. Spring boot将配置属性注入到bean类中

    一.@ConfigurationProperties注解的使用 看配置文件,我的是yaml格式的配置: // file application.yml my: servers: - dev.bar.c ...

  4. Spring4学习笔记二:Bean配置与注入相关

    一:Bean的配置形式 基于XML配置:在src目录下创建 applicationContext.xml  文件,在其中进行配置. 基于注解配置:在创建bean类时,通过注解来注入内容.(这个不好,因 ...

  5. Springboot学习笔记(六)-配置化注入

    前言 前面写过一个Springboot学习笔记(一)-线程池的简化及使用,发现有个缺陷,打个比方,我这个线程池写在一个公用服务中,各项参数都定死了,现在有两个服务要调用它,一个服务的线程数通常很多,而 ...

  6. Spring boot将配置属性注入到bean 专题

    https://blog.csdn.net/wangmx1993328/article/details/81002901 Error starting ApplicationContext. To d ...

  7. spring_入门配置和注入

    Spring的获取容器: public static void main(String[] args) { //获取核心容器 BeanFactory延迟加载对象 ApplicationContext ...

  8. 转载:ASP.NET Core 在 JSON 文件中配置依赖注入

    在以前的 ASP.NET 4+ (MVC,Web Api,Owin,SingalR等)时候,都是提供了专有的接口以供使用第三方的依赖注入组件,比如我们常用的会使用 Autofac.Untiy.Stri ...

  9. 外部配置属性值是如何被绑定到XxxProperties类属性上的?--SpringBoot源码(五)

    注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 前言 本篇接 SpringBoot是如何实现自动配置的?--SpringBoot源码(四) 温故而知新,我们来简单回顾一下上 ...

  10. idea下使用autowire注解注入对象,结果初始化不到类

    如果idea下使用autowire注解注入对象,结果初始化不到类,明明使用快捷键alt+insert是可以找到该注入的对象的. 而我们在使用的时候,缺报错了??? 注意,当我们在注入对象的时候,我们留 ...

随机推荐

  1. 百度杯 十二月 what_the_fuck

    对于这道题,我还真的想说 what_the_fuck !! 这道题拿到就只发觉一个格式化字符串漏洞,其他的就找不到了 . unsigned __int64 sub_4008C5() { char s; ...

  2. linux awk进阶篇

    上一篇主要是awk的进本应用.本节是awk的进阶篇 ACTION:除去常用的print和printf还有以下几个 expression:表达式 如$1>3 control statements: ...

  3. 最全 HTTP 安全响应头设置指南

    销售“安全记分卡”的公司正在崛起,并已开始成为企业销售的一个因素.这些公司组合使用 HTTP 安全报头和 IP 信誉来进行评级.不过,在很大程度上,公司的得分取决于对外开放网站上设置的安全响应报头.本 ...

  4. word2vec:CBOW和skip-gram模型

    1.CBOW模型 之前已经解释过,无论是CBOW模型还是skip-gram模型,都是以Huffman树作为基础的.值得注意的是,Huffman树中非叶节点存储的中间向量的初始化值是零向量,而叶节点对应 ...

  5. yum运行报错:libcurl.so.4: cannot open shared object file: No such file or directory

    /usr/lib64/目录下存在libcurl.so.4文件 CURL的动态库找不到,这里我们加入到ld.so.conf [root@localhost bin]#  vim /etc/ld.so.c ...

  6. Linux如何切换图形界面和命令行界面

    在命令行,输入 init 3 命令,并按回车键执行,切换到命令行界面 切换到命令行界面后,在界面上只显示一个闪烁的光标,按下 Ctrl+Alt+F6(非虚拟机)或者 Alt+F6(虚拟机),显示用户登 ...

  7. Spring(Bean)1

    Spring支持3种依赖注入的方式 (DI依赖注入)*属性注入 (配置bean set方法注入) <bean id="car" class="spring.bean ...

  8. Nginx安装、默认虚拟主机、Nginx用户认证和域名重定向

    6月7日任务 12.6 Nginx安装12.7 默认虚拟主机12.8 Nginx用户认证12.9 Nginx域名重定向 扩展nginx.conf 配置详解 http://www.ha97.com/51 ...

  9. SSO单点登录思路

    SSO (Single Sign On) 什么是单点登录: 在大型的互联网公司中会有多个系统, 多个项目, 虽然这些项目都属于同一家公司, 但是项目本身其实都是独立的, 那多个系统可不可以实现共享同一 ...

  10. Bean中要使用配置文件中的值,使用set方法注入

    /** * Sensors Analytics Bean * @author Feng */ @Component public class SensorsAnalyticsBean { /*** * ...