当php面向对象开发过程中,随着项目越来越大,需要通过include或require引入的文件越来越多,每个php脚本开头都要引入一大堆文件引入,不便于项目的管理,当有类更新时,也容易导致项目出现报错。所以就需要类的自动载入功能。php通过__autoload和spl_autoload_register函数来实现。__autoload函数在PHP 7.2中已经废弃,不推荐使用。
一、__autoload
当一个类实例化时会把类名以参数方式传给_autoload函数,spl_autoload_register也一样。然后通过目录+类名的方式引入文件。
不使用自动加载时引入文件:
require 'a.php'; // class name a
require 'b.php'; // class name b
require 'c.php'; // class name c
使用自动加载时引入文件,假设目录为/test:
function __autoload($class){
require_once '/test/' . $class . '.php';
}
$a = new a(); // 类名a即__autoload参数名 $class = a
$a = new b(); // $class = b
$a = new c(); // $class = c
二、spl_autoload_register
当项目有多个模块时,__autoload不能满足需求,__autoload只能定义一次。如果需要多次使用autoload 函数时,spl_autoload_register() 满足了此类需求。 它实际上创建了 autoload 函数的队列,按定义时的顺序逐个执行。spl_autoload_register将函数注册到SPL __autoload函数队列中。如果该队列中的函数尚未激活,则激活它们。
1.加载一个模块,匿名函数方式
spl_autoload_register(function ($class) {
require __DIR__ . '/class/' . $class . '.class.php';
});
2.加载多模块时,注册多个自定义自动装载函数
spl_autoload_register('homeAutoloader');
spl_autoload_register('adminAutoloader');
function homeAutoloader($class) {
require_once __DIR__ . '/Home/class/' . $class . '.class.php';
}
function adminAutoloader($class) {
require_once __DIR__ . '/Admin/class/' . $class . '.class.php';
}
这时只要实例化后的类都会在一个队列中,如:
require_once __DIR__ . '/Home/class/index.class.php';
require_once __DIR__ . '/Home/class/edit.class.php';
require_once __DIR__ . '/Admin/class/index.class.php';
require_once __DIR__ . '/Admin/class/index.class.php';
上面的方式虽然实现了类的自动加载,但当出现同样的类名,就会报错。所以需要引入一些规范和命名空间来解决。
3.类自动加载PSR规范
PSR 是 PHP Standard Recommendations 的简写,由 PHP FIG 组织制定的 PHP 规范,是 PHP 开发的实践标准。现在的标准是PSR-4规范,在此之前还有PSR-1、PSR-2、PSR-3规范,PSR-1规范已弃用。PSR-4规范是在PSR-1、PSR-2规范中更新和扩展而来。
PSR-1规范要求(已弃用):
*命名空间结构必须是路径的一部分;
*类名称中的每个 _ 字符也会被转换成文件夹路径分隔符;即:\app\controller\Index_Index 。index目录中的index.php类,用下划线间隔;
*类文件名必须是 .php 后缀;
PSR-2规范要求:
*代码 必须 使用 4 个空格符进行缩进;
*每行的字符数应该软性保持在 80 个之内;
*namespace命名空间声明语句和 use 声明语句块后面必须 插入一个空白行;
*类和类中的方法开始花括号{和结束花括号}必须独自占有用一行;
*类的属性和方法 必须 添加访问修饰符(private、protected 以及 public),abstract 以及 final 必须 声明在访问修饰符之前,而 static 必须 声明在访问修饰符之后;
*控制结构的关键字后 必须 要有一个空格符,而调用方法或函数时不用空格;
*控制结构的开始花括号{必须 写在声明的同一行,而结束花括号}必须 写在主体后自成一行;
*控制结构的开始左括号后和结束右括号前不能有空格符;
PSR-3规范要求:
PSR-4规范要求:
*全限定类名具有以下形式:\NamespaceName\SubNamespaceNames\ClassName;
*全限定类名必须拥有一个顶级命名空间名称,也称为供应商命名空间(vendor namespace);
*全限定类名可以有一个或者多个子命名空间名称;
*全限定类名必须有一个最终的类名,不能是这样的形势 \NamespaceName\SubNamespaceNames*\;
*去除了psr-1中的下划线来间隔文件夹和文件名,下划线在psr-4中无意义;
*全限定类名可以是任意大小写字母的组合;
*所有类名的引用必须区分大小写;
*全限定类名的加载过程:
*在全限定的类名(一个「命名空间前缀」)中,一个或多个前导命名空间和子命名空间组成的连续命名空间,不包括前导命名空间的分隔符,至少对应一个「根目录」;
*「命名空间前缀」后面的相邻子命名空间与根目录下的目录名称相对应(且必须区分大小写),其中命名空间的分隔符表示目录分隔符;
*最终的类名与以.php 结尾的文件名保持一致,这个文件的名字必须和最终的类名相匹配(意思就是如果类名是 FooController,那么这个类所在的文件名必须是 FooController.php);
*自动加载文件禁止抛出异常,禁止出现任何级别的错误,也不建议有返回值;
psr全规范参考:https://learnku.com/docs/psr
4.实现一个简单的mvc类的自动加载
执行过程:在入口index.php文件中引入自动加载类文件并调用。每次调用类方法时,通过spl_autoload_register函数穿类名路径的方式,处理后引用类文件。
<?php
define('BASE_DIR', __DIR__);
// 引入自动加载
require __DIR__ . '/' . 'loader.php';
Loader::autoLoad();
// 调用Index控制器中index方法
\app\controller\index\Index::index();
// 调用Test控制器中test方法
\app\controller\test\Test::test();
自动加载类loader.php
<?php
/**
* 类的自动加载
* Class Loader
*/
class Loader
{
public static function autoLoad()
{
// 注册类
spl_autoload_register(function ($class) {
$class = str_replace('\\', DIRECTORY_SEPARATOR, $class);
$filePath = BASE_DIR . DIRECTORY_SEPARATOR . $class . '.php';
if (file_exists($filePath)) {
include $filePath;
} else {
echo 'Class Not Found !';
}
});
}
}
控制器Index.php
<?php
namespace app\controller\index;
class Index
{
public static function index()
{
echo 'Index.php: Index Controller' . "<br/>";
}
}
控制器Test.php
<?php
namespace app\controller\test;
use \app\model\index\Index as IndexModel;
class Test
{
public static function test()
{
echo 'Test.php: Test Controller' . ' ';
// 控制器调用模型
IndexModel::index();
}
}
模型Index.php
<?php
namespace app\model\index;
class Index
{
public static function index()
{
echo 'Call Index Model ' . "<br/>";
}
}
以上就是PHP--类的自动加载。保护好你的梦想,等到它开花结果的那天,它会让你俯视所有以前看低你的人。更多关于PHP--类的自动加载请关注haodaima.com其它相关文章!