PHP框架中的各个目录下面的各个.php文件是如何实现加载的,他上网搜索,一搜一大把,都是再说php中有自动加载函数,是自动加载函数完成类文件的自动加载的,但是具体的还是不明白。是的,框架的自动载入的完成的确是依靠PHP提供的自动载入的函数来完成,但是除此以外,还有几个需要注意点,如果不搞明白,就不能真正的理解框架具体的实现方式。那么这里就总结一下: (1):总所周知,php完成自动加载是依靠__autoload()函数或者spl_autoload_register()函数来实现,具体的使用方法大家都知道,这里就不赘述了。这里说一下两者之间的区别。 目前,实现自动加载,大家几乎都使用spl_autoload_register()函数,而不是使用__autoload()函数,这是因为,在同一个脚本中__autoload()函数不能够重复进行定义,而spl_autoload_register()函数却可以实现注册多次加载函数,这样我们就可以更加灵活的进行文件的自动加载了。 下面的代码因为重复定义了__autoload()函数,所以会报错。 <?php //定义加载函数1 function __autoload($class_name){ //加载文件 require_once("./".$class_name.".php"); } //定义加载函数2 function __autoload($class_name){ //加载文件 require_once("./".$class_name.".php"); } ?> 但是下面使用spl_autoload_register()函数就不会报错: <?php function autoload_one($class_name){ require_once(""); } function autoload_two($class_name){ require_once(""); } spl_autoload_register('autoload_one'); spl_autoload_register('autoload_two'); ?> (2):参考上面的两个函数的代码,传递的参数都是$class_name,也就是需要加载的类的名称。如果我们实例化一个类,就会自动的将该类的名称赋值给$class_name。如果我们实例化一个带有命名空间的类,就会将该类所处的命名空间以及该类的名称传递给$class_name。看下面的代码: <?php function __autoload($class_name){ require_once("./".$class_name.".php"); echo $class_name."<br/>"; //打印出User\Parent } $a = new User\Parent(); //实例化User命名空间下的Parent类 ?> 好了,现在我们就可以得到想要实例化的类的名称,那么下面的问题就是如何根据传递过来的类的名字来找到该类文件,并进行加载了。 (3):在了解如何根据传递过来的类的名称(包括命名空间)去找类之前,我们还必须要了解一下PHP编程的规范,了解了规范,你就会彻底明白到底是怎么回事。这里说的PHP开发规范指的是PSR规范,它是PHP开发的事实标准,主流的PHP开发框架都是遵循PSR开发规范。比如ThinkPHP框架就支持PSR开发标准。
PSR规范目前包含五个具体的规范(包括PSR-0,PSR-1,PSR-2,PSR-3,PSR-4)。这里我们具体的说一下PSR-0以及PSR-4规范,其他的规范我们这里就不提,有兴趣的同学可以自己百度。PSR-0规范如下: 1):命名空间必须与绝对路径一致。 2):类名的首字母必须要大写。 3):除了入口文件以外,其他的.php文件中必须只有一个类,不能有可执行的代码。 根据PSR-o规范,命名空间空间必须要与绝对路径一致,也就是说如果你要将一个名为HomeController的类文件设置在App\User\Controller的命名空间之下,那么就必须要将该文件放到当前目录下面(入口文件)下面的./App/User/Controller文件夹下面。反过来一样,如果你需要在./App/User/Controller文件夹下面创建一个类文件,那么这个类文件的命名空间也必须是App\User\Controller。 PSR-4规范基本和PSR-0规范一致,区别在与PSR-4是对下划线(underscore)的定义不同。PSR-4中,在类名中使用下划线没有任何特殊含义。而PSR-0则规定类名中的下划线_会被转化成目录分隔符。 了解了上面的三点,我们就可以理清主流PHP框架中实现类文件加载的机制了。 (1):在入口文件中定义类文件的加载处理函数,比如说spl_autoload_register()函数。 (2):index.php处理用户的请求,处理传递过来的参数,解析路由,分析出需要请求的类名,方法名。 (3):实例化类,根据传入的类名称,根据PSR-0/PSR-4规范,分析出类文件的路径,进行加载 大体的步骤就是这样的,当然了,一个成熟的框架真正的加载流程要比上面说的复杂的多得多,有兴趣的可以研究框架源码。 补:另外,因为主流的框架都广泛的采用命名空间,所以就会大量的使用use来引用其他各个命名空间下定义的各个类。有些同学可能没有看到require()来加载类文件,所以就以为use可以自动的完成文件的加载。其实并不是这样的,use并不会进行类文件的加载。之所以use之后就完成了加载,还是因为框架定义了自动加载函数的原因,使用use来引入类与使用new来实例化类的时候,都会触发类的自动加载。 (责任编辑:最模板) |