PHP的命名空间和spl_autoload_register
从最简单的开始。
当文件都在同一个目录时
新建一个文件Application.php,内容如下:
<?php
namespace PPP;
class Application{
public function world()
{
echo "hello";
}
}Application.php文件的命名空间是PPP。
在同目录下再新建一个文件hello.php,内容如下:
<?php
//------------------------
// php 服务器500错误解决
// 开启php.ini中的display_errors指令
ini_set('display_errors',1);
// 通过error_reporting()函数设置,输出所有级别的错误报告
error_reporting(E_ALL);
//------------------------
use PPP\Application;
$hk = new Application;
var_dump($hk);在没有require或者include的情况下,仅仅使用use关键字是无法正常实例化Application对象的,因为use只是逻辑上的引用。PHP不知道PPP\Application实际的物理位置。
现在添加require
<?php
//------------------------
// php 服务器500错误解决
// 开启php.ini中的display_errors指令
ini_set('display_errors',1);
// 通过error_reporting()函数设置,输出所有级别的错误报告
error_reporting(E_ALL);
//------------------------
require_once __DIR__ . "/Application.php";
use PPP\Application;
$hk = new Application;
var_dump($hk);现在程序能正常运行了。
现在在当前目录下创建一个文件夹PPP,并把Application.php文件放到PPP目录,这时候就需要重新更改require的路径了。
<?php
//------------------------
// php 服务器500错误解决
// 开启php.ini中的display_errors指令
ini_set('display_errors',1);
// 通过error_reporting()函数设置,输出所有级别的错误报告
error_reporting(E_ALL);
//------------------------
require_once __DIR__ . "/PPP/Application.php";
use PPP\Application;
$hk = new Application;
var_dump($hk);还可以使用spl_autoload_register()和命名空间
<?php
//------------------------
// php 服务器500错误解决
// 开启php.ini中的display_errors指令
ini_set('display_errors',1);
// 通过error_reporting()函数设置,输出所有级别的错误报告
error_reporting(E_ALL);
//------------------------
spl_autoload_register();
use PPP\Application;
$hk = new Application;
var_dump($hk);但是使用spl_autoload_register()的话,文件的名称与路径要严格和namespace命名空间一致。当Application文件所在的目录不是PPP时就会发生错误。
但是这些都是发生在运行的hello.php文件所在的目录下的,包括PPP目录也是和hello.php在同一个目录的。
如果我们把PPP目录放到其他地方,上面的代码就又失效了。
当文件在不同目录时
在继续之前,要先了解PHP中获取路径的方法
echo __FILE__ ; // 获取当前所在文件的绝对路径及地址,结果:D:\aaa\my.php
echo dirname(__FILE__); // 取得当前文件所在的绝对目录,结果:D:\aaa\
echo dirname(dirname(__FILE__)); //取得当前文件的上一层目录名,结果:D:\ 知道了PHP如何获取路径后,我们定义以下的目录结构:
/root/
|
|---/PHP_Object/
| |
| |----hello.php
|
|---/PPP/
| |
| |----Application.php
|
|---/test/
| |
| |----/aaa/
| |
| |----Blao.php
|三个文件在不同的目录。先来看Application.php文件
<?php
namespace root\PPP;
class Application{
public function world()
{
echo "hello world";
}
}namespace命名空间对应实际文件位置root\PPP
spl_autoload_register()还可以接受一个参数,但是这个参数是匿名函数
hello.php文件
<?php
$namespaces = function ($path){
if(preg_match('/\\\\/',$path))
{
$path = str_replace('\\',DIRECTORY_SEPARATOR,$path);
}
$path = dirname(dirname(dirname(__FILE__))) . "/" . "$path";
//var_dump($path);
if(file_exists("{$path}.php"))
{
require_once("{$path}.php");
}
};
\spl_autoload_register($namespaces);
$blah = new root\PPP\Application();
$blah->world();
echo "<br/>";
$www = new root\test\aaa\Blao();
$www->nd();上面的代码中,先定义了一个匿名参数,这个匿名参数的作用是将namesapce命名空间中的反斜杠(\)替换为路径斜杠(/),dirname(dirname(dirname(__FILE__)))这里得到的就是当前目录的上级目录,也就是root目录。
当PHP引擎要实例化Application类时,就会运行spl_autoload_register()去自动加载需要的类文件,对于Blao类也是同理。
参考资料:
php不同路径的类文件自动加载
关于 PHP 命名空间的一个疑问
《深入PHP·面向对象、模式与实践》5.1.2 自动加载
评论已关闭