PHP 实现自动加载的前世今生
说明
参考文章:https://www.cnblogs.com/lucklyphp/p/10700454.html
参考文章:https://segmentfault.com/a/1190000014948542
requrie 和 include 阶段
<h5>require 和 include的区别</h5>
首先include和require都是引入指定的文件。_once表示只引入一次,已经引入过一次的文件接下来就不会再引入。
require 和 include的区别主要有以下几点:
- 加载失败的处理方式不同
include在引入不存文件时产生一个警告且脚本还会继续执行, require则会导致一个致命性错误且脚本停止执行。
include()是有条件包含函数,而 require()则是无条件包含函数
<?php
if(FALSE){include 'file.php'; //file.php不会被引入} if(FALSE){require 'file.php'; //file.php将会被引入}
require通常使用方法,这个函数通常放在 PHP 程序的最前面,PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部份。常用的函数,亦可以这个方法将它引入网页中。
include通常使用方法,这个函数一般是放在流程控制的处理部分中。PHP 程序网页在读到 include 的文件时,才将它读进来。这种方式,可以把程序执行时的流程简单化
理论上来说:include和require后面加不加括号对执行结果没有区别,但是加上括号效率较低,所以后面能不加括号就不加括号。
<h5>引用的问题</h5>
在PHP5之前,在文件中引用外部类的话只能用require 或者 indlude,在小项目开发中,这种模式还可以接受,但是随着项目的逐渐扩大,这种直接引入的方式会逐渐显现出一些弊端。
1.各个文件相互引用,文件套文件,文件管理混乱
2.使用require引入文件,如果包含语法错误,整个文件都将无法访问。
3.如果我们在使用到外部类的时候再去加载类,而不是一开始就全部装载进来也能够节省一部分性能。
自动加载机制
PHP5的发布为文件引入带来了一个新的解决机制:类的自动加载(autoload)机制。autoload机制 可以使得 PHP 程序有可能在使用类时才自动包含类文件,而不是一开始就将所有的类文件include进来,这种机制也称为 Lazy loading (惰性加载)。
总结起来,自动加载功能带来了几处优点:
1.使用类之前无需 include / require
2.使用类的时候才会 include / require 文件,实现了 lazy loading ,避免了 include / require 多余文件。
3.无需考虑引入 类的实际磁盘地址 ,实现了逻辑和实体文件的分离。
__autoload阶段
PHP5版本带来类自动加载机制的同时提供了__autoload类自动加载方法。
当我们在使用一个类时,如果发现这个类没有加载,就会自动运行 __autoload() 函数,我们就可以在这个方法中实现类的自动加载。
以下是一个小的案例:
<?php function __autoload($classname)
{
require_once ($classname . ".class.p;
}
__autoload()方法极大的方便了开发者们引入外部文件,但是到了开发后期,开发者们又发现了新的问题。__autoload()函数是全局函数,在项目中只能定义一次,这就意味着我们项目所有的类名与文件名对应的逻辑规则都要在这个函数里面实现,这样的话 __autoload() 函数有可能会非常复杂,而且不易于我们后期维护。
幸运的是,随着官方SPL标准类库的引入,PHP官方提供了一个全新的函数spl_autoload_register() 来帮我们处理这个问题。我们可以不同的自定义加载函数来处理不同的文件,然后听过将函数注册到SPL __autoload函数队列中。按定义时的顺序逐个执行。(官方7.2版本之后弃用了__autoload()方法,推荐使用)
spl_autoload_register
spl_autoload_register ([ callable $autoload_function [, bool $throw = true [, bool $prepend = false ]]] ) : bool
简单示例:
如果同时用spl_autoload_register注册了一个类的方法和__autoload函数,那么,会根据注册的先后,如果在第一个注册的方法或函数里加载了类文件,就不会再执行第二个被注册的类的方法或函数。反之就会执行第二个被注册的类的方法或函数。
<?php
class autoloader {
public static $loader;
public static function init() {
if (self::$loader == NULL)
self::$loader = new self ();
return self::$loader;
}
public function __construct() {
spl_autoload_register ( array ($this, 'model' ) );
spl_autoload_register ( array ($this, 'helper' ) );
spl_autoload_register ( array ($this, 'controller' ) );
spl_autoload_register ( array ($this, 'library' ) );
}
public function library($class) {
set_include_path ( get_include_path () . PATH_SEPARATOR . '/lib/' );
spl_autoload_extensions ( '.library.php' );
spl_autoload ( $class );
}
public function controller($class) {
$class = preg_replace ( '/_controller$/ui', '', $class );
set_include_path ( get_include_path () . PATH_SEPARATOR . '/controller/' );
spl_autoload_extensions ( '.controller.php' );
spl_autoload ( $class );
}
public function model($class) {
$class = preg_replace ( '/_model$/ui', '', $class );
set_include_path ( get_include_path () . PATH_SEPARATOR . '/model/' );
spl_autoload_extensions ( '.model.php' );
spl_autoload ( $class );
}
public function helper($class) {
$class = preg_replace ( '/_helper$/ui', '', $class );
set_include_path ( get_include_path () . PATH_SEPARATOR . '/helper/' );
spl_autoload_extensions ( '.helper.php' );
spl_autoload ( $class );
}
}
//call
autoloader::init ();
?>
命名空间跟Composer
结尾
腹有诗书气自华,最是书香能致远。