Gitlib Gitlib
首页
  • 分类
  • 标签
  • 归档
  • Golang开发实践万字总结
  • MySQL核心知识汇总
  • Redis实践总结
  • MQ实践万字总结
  • Docker数据持久化总结
  • Docker网络模式深度解读
  • 常用游戏反外挂技术总结
  • 读书笔记
  • 心情杂货
  • 行业杂谈
  • 友情链接
关于我
GitHub (opens new window)

Ravior

以梦为马,莫负韶华
首页
  • 分类
  • 标签
  • 归档
  • Golang开发实践万字总结
  • MySQL核心知识汇总
  • Redis实践总结
  • MQ实践万字总结
  • Docker数据持久化总结
  • Docker网络模式深度解读
  • 常用游戏反外挂技术总结
  • 读书笔记
  • 心情杂货
  • 行业杂谈
  • 友情链接
关于我
GitHub (opens new window)
  • PHP

    • PHP-FPM使用指南
    • PHP7新特性总结
    • PHP安全编程
    • PHP安全配置总结
    • PHP变量的值类型和引用类型
    • PHP标准规范PSR
    • PHP操作Zookeeper实践
    • PHP错误和异常处理机制详解
    • PHP的Session运行机制
    • PHP底层运行机制和原理
    • PHP反射模拟实现注解路由
    • PHP高级用法总结
    • PHP开发常用文档总结
    • PHP开发入门:Memcached扩展安装
    • PHP开发入门:PHP7安装部署
    • PHP开发入门:Redis扩展安装
    • PHP开发SPL总结
    • PHP框架常见URL模式
    • PHP扩展开发入门
    • PHP垃圾回收机制
    • PHP类的自动加载
      • __autoload
        • 语法
        • 用法
        • 缺陷
      • splautoloadregister
        • 语法
        • 用法
    • PHP输入输出流
    • PHP微服务开发指南
    • PHP协程
    • PHP写时拷贝技术
    • PHP性能优化之Opcache
    • PHP依赖注入和控制反转
    • PHP运行模式(SAPI)
    • PHP中file_get_contents与curl区别
    • RPC的简单实现
    • Protobuf:高效数据结构化工具
    • P3P协议详解
    • Laravel之集合(Collection)总结
    • Laravel实践总结
    • Laravel之ORM总结
    • 中高级PHP实践总结
    • PHP Socket编程实战
  • Golang

  • Python

  • Javascript

  • 其他语言

  • 编程语言
  • PHP
Ravior
2018-05-19
目录

PHP类的自动加载

在PHP开发过程中,如果希望从外部引入一个class,通常会使用include和require方法,去把定义这个class的文件包含进来。这个在小规模开发的时候,没什么大问题。但在大型的开发项目中,这么做会产生大量的require或者include方法调用,这样不因降低效率,而且使得代码难以维护,况且require_once的代价很大。

在PHP5之前,各个PHP框架如果要实现类的自动加载,一般都是按照某种约定自己实现一个遍历目录,自动加载所有符合约定规则的文件的类或函数。在PHP5后,当加载PHP类时,如果类所在文件没有被包含进来,或者类名出错,Zend引擎会自动调用**__autoload()函数。此函数需要用户自己实现__autoload()函数。 在PHP5.1.2版本后,可以使用spl_autoload_register()**函数自定义自动加载处理函数。当没有调用此函数,默认情况下会使用SPL自定义的spl_autoload函数。

# __autoload

__autoload() 是php中的一个魔术方法,在代码中当调用不存在的类时会自动调用该方法。

# 语法

_autoload ( string $class ) : void  // class: 待加载的类名
1

# 用法

<?php

function __autoload($className) 
{
	echo 'autoload自动加载', $className,'<br />';
}

$myClass1 = new MyClass1();
1
2
3
4
5
6
7
8

如果调用某个未经include/require的类,在报错之前,还可以**__autoload()函数得到一次介入机会,系统会调用__autoload()函数,并把类名传给__autoload()函数,就可以在__autoload()**里加载需要的类。

例如:

<?php

function __autoload($classname) {
        require_once ($classname . ".class.php");
}
1
2
3
4
5

因此,当有大量的类文件要包含的时候,我们只要确定相应的规则,然后在__autoload()函数中,将类名与实际的磁盘文件对应起来,就可以实现lazy loading的效果。

# 缺陷

但现在问题来了,假如在一个系统的实现中,假如需要使用很多其它的类库,这些类库可能是由不同的开发工程师开发,其类名与实际的磁盘文件的映射规则不尽相同。这时假如要实现类库文件的自动加载,就必须在**__autoload()函数中将所有的映射规则全部实现,因此__autoload()函数有可能会非常复杂,甚至无法实现。最后可能会导致__autoload()函数十分臃肿,这时即便能够实现,也会给将来的维护和系统效率带来很大的负面影响。所有问题都出现在__autoload() 是全局函数只能定义一次** ,那么如何来解决这个问题呢?答案就是使用一个 __autoload调用堆栈 ,不同的映射关系写到不同的 __autoload函数 中去,然后统一注册统一管理,这个就是 PHP5 引入的 SPL Autoload。

# spl_autoload_register

**spl_autoload_register()是SPL(Standard PHP Library)**提供的方法。

# 语法

spl_autoload_register ([ callable $autoload_function [, bool $throw = true [, bool $prepend = false ]]] ) : bool
1
  • autoload_function:注册的自动装载函数
  • throw:此参数设置了 autoload_function 无法成功注册时, **spl_autoload_register()**是否抛出异常
  • prepend:如果是 true,spl_autoload_register() 会添加函数到队列之首,而不是队列尾部

# 用法

一旦调用spl_autoload_register()函数,当调用未定义类时,系统会按顺序调用注册到spl_autoload_register()函数的所有函数,而不是自动调用__autoload()函数。

<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);

use Autoload\TestClass;

function __autoload($className) 
{
	echo 'autoload自动加载', $className,'<br />';
}

spl_autoload_register(function($className){
	echo 'spl autoload自动加载1', $className,'<br />';
});

spl_autoload_register(function($className){
	echo 'spl autoload自动加载2', $className,'<br />';
});

$myClass1 = new MyClass1();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

结果输出:

spl autoload自动加载1MyClass1
spl autoload自动加载2MyClass1

Fatal error: Uncaught Error: Class 'MyClass1' not found in /www/websites/www/gitlib/php/autoload.php:20 Stack trace: #0 {main} thrown in /www/websites/www/gitlib/php/autoload.php on line 20
1
2
3
4

还可以调用spl_autoload_register()函数以注册一个回调函数,而不是为函数提供一个字符串名称。如提供一个如array('class','method')这样的数组,使得可以使用某个对象的方法。

// 静态方法
class MyClass 
{
	public static function autoload($className) 
	{
		echo 'class autoload自动加载', $className,'<br />';
	}
}

spl_autoload_register(array('MyClass', 'autoload'));

// 实例
$myClass = new MyClass();

spl_autoload_register(array('myClass', 'autoload'));

$myClass1 = new MyClass1();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

这样,就可以通过**spl_autoload_regsiter()**这个函数注册多个我们自己的 autoload() 函数,当 PHP 找不到类名时,PHP就会调用这个堆栈,然后去调用自定义的 autoload() 函数,实现自动加载功能。

#PHP
上次更新: 2022/12/01, 11:09:34
PHP垃圾回收机制
PHP输入输出流

← PHP垃圾回收机制 PHP输入输出流→

最近更新
01
常用游戏反外挂技术总结
11-27
02
Golang开发实践万字总结
11-11
03
Redis万字总结
10-30
更多文章>
Theme by Vdoing | Copyright © 2011-2022 Ravior | 粤ICP备17060229号-3 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式