自动加载
实现自动加载最简单的方式就是使用 __autoload 魔术方法
通过这个简单的例子可以发现,在类的实例化过程中,系统所做的工作大致是这样的:
/* 模拟系统实例化过程 */
function instance($class)
{
// 如果类存在则返回其实例
if (class_exists($class, false)) {
return new $class();
}
// 查看 autoload 函数是否被用户定义
if (function_exists('__autoload')) {
__autoload($class); // 最后一次引入的机会
}
// 再次检查类是否存在
if (class_exists($class, false)) {
return new $class();
} else { // 系统:我实在没辙了
throw new Exception('Class Not Found');
}
}
(我这里创建了一个 HelloWorld 类用作演示)接下来我们就要定义 __autoload 的具体逻辑,使它能够实现自动加载:
function __autoload($class)
{
// 根据类名确定文件名
$file = $class . '.php';
if (file_exists($file)) {
include $file; // 引入PHP文件
}
}
new HelloWorld();
/**
* 输出 <h1>HelloWorld</h1>
*/
命名空间
主要目的是解决命名冲突的问题。
使用限定类名和完全限定类名的区别。(完全限定类名 = 当前命名空间 + 限定类名)
/* 导入命名空间 */
use 百度\李彦宏;
new 李彦宏(); // 百度\李彦宏(实际结果)
/* 设置别名 */
use 百度\李彦宏 AS CEO;
new CEO(); // 百度\李彦宏(实际结果)
/* 任何情况 */
new \百度\李彦宏();// 百度\李彦宏(实际结果)
使用命名空间只是让类名有了前缀,不容易发生冲突,系统仍然不会进行自动导入。这里我们使用 spl_autoload_register() 函数来实现
spl_autoload_register()
PSR-4规范规范规定了一个完全限定类名需要具有以下结构:
\<顶级命名空间>(\<子命名空间>)*\<类名>
PSR-4 规范中必须要有一个顶级命名空间,它的意义在于表示某一个特殊的目录(文件基目录)。子命名空间代表的是类文件相对于文件基目录的这一段路径(相对路径),类名则与文件名保持一致(注意大小写的区别)。
我们就以解析 \app\lib\pp 为例,编写一个简单的 Demo:
更目录下创建一个入口文件内容如下:
<?php
use app\lib\pp;
spl_autoload_register(function ($class) {
/* 顶级命名空间路径映射 */
$vendor_map = array(
'app' => __DIR__ . DIRECTORY_SEPARATOR . 'app',
);
// 取出顶级命名空间[app]
$vendor = substr($class, 0, strpos($class, '\\'));
$vendor_dir = $vendor_map[$vendor]; // 文件基目录
$rel_path = dirname(substr($class, strlen($vendor))); // 相对路径
$file_name = basename($class) . '.php'; // 文件名
$file = $vendor_dir . $rel_path . DIRECTORY_SEPARATOR . $file_name;
/* 引入相关文件 */
if (file_exists($file)) {
include $file;
}
});
(new pp())->getPname();
在app\lib目录下创建pp.php
<?php
namespace app\lib;
class pp{
function getPname(){
echo "pname";
}
}
目录结构:
参考:https://www.cnblogs.com/woider/p/6443854.html