1.非限定名称,或不包含前缀的类名称,例如 $comment = new Comment(); 如果当前命名空间是BlogArticle,Comment将被解析为、BlogArticleComment。如果使用Comment的代码不包含在任何命名空间中的代码(全局空间中),则Comment会被解析为Comment。
注意: 如果文件的开头有使用use关键字 use one woComment; 则Comment会被解析为 **one woComment**。
2.限定名称,或包含前缀的名称,例如 $comment = new ArticleComment(); 如果当前的命名空间是Blog,则Comment会被解析为BlogArticleComment。如果使用Comment的代码不包含在任何命名空间中的代码(全局空间中),则Comment会被解析为ArticleComment。
3.完全限定名称,或包含了全局前缀操作符的名称,例如 $comment = new ArticleComment(); 在这种情况下,Comment总是被解析为ArticleComment。
spl_autoload
接下来让我们要在含有命名空间的情况下去实现类的自动加载。我们使用 spl_autoload_register() 函数来实现,这需要你的 PHP 版本号大于 5.12。spl_autoload_register函数的功能就是把传入的函数(参数可以为回调函数或函数名称形式)注册到 SPL __autoload 函数队列中,并移除系统默认的 **__autoload()** 函数。一旦调用 spl_autoload_register() 函数,当调用未定义类时,系统就会按顺序调用注册到 spl_autoload_register() 函数的所有函数,而**不是自动调用 __autoload()** 函数。
现在, 我们来创建一个 Linux 类,它使用 os 作为它的命名空间(建议文件名与类名保持一致):
<?php namespace os; // 命名空间 class Linux // 类名 { function __construct() { echo '<h1>' . __CLASS__ . '</h1>'; } }
接着,在同一个目录下新建一个 index.php文件,使用 spl_autoload_register 以函数回调的方式实现自动加载:
<?php spl_autoload_register(function ($class) { // class = osLinux /* 限定类名路径映射 */ $class_map = array( // 限定类名 => 文件路径 'os\Linux' => './Linux.php', ); /* 根据类名确定文件路径 */ $file = $class_map[$class]; /* 引入相关文件 */ if (file_exists($file)) { include $file; } }); new osLinux();
这里我们使用了一个数组去保存类名与文件路径的关系,这样当类名传入时,自动加载器就知道该引入哪个文件去加载这个类了。但是一旦文件多起来的话,映射数组会变得很长,这样的话维护起来会相当麻烦。如果命名能遵守统一的约定,就可以让自动加载器自动解析判断类文件所在的路径。接下来要介绍的PSR-4 就是一种被广泛采用的约定方式
PSR-4规范
PSR-4 是关于由文件路径自动载入对应类的相关规范,规范规定了一个完全限定类名需要具有以下结构:
<顶级命名空间>(<子命名空间>)*<类名>
PSR-4 规范中必须要有一个顶级命名空间,它的意义在于表示某一个特殊的目录(文件基目录)。子命名空间代表的是类文件相对于文件基目录的这一段路径(相对路径),类名则与文件名保持一致(注意大小写的区别)。
举个例子:在全限定类名 appview ewsIndex 中,如果 app 代表 C:Baidu,那么这个类的路径则是 C:Baiduview ewsIndex.php.我们就以解析 appview ewsIndex 为例,编写一个简单的 Demo:
<?php $class = 'appview ewsIndex'; /* 顶级命名空间路径映射 */ $vendor_map = array( 'app' => 'C:Baidu', ); /* 解析类名为文件路径 */ $vendor = substr($class, 0, strpos($class, '\')); // 取出顶级命名空间[app] $vendor_dir = $vendor_map[$vendor]; // 文件基目录[C:Baidu] $rel_path = dirname(substr($class, strlen($vendor))); // 相对路径[/view/news] $file_name = basename($class) . '.php'; // 文件名[Index.php] /* 输出文件所在路径 */ echo $vendor_dir . $rel_path . DIRECTORY_SEPARATOR . $file_name;
更多PHP相关知识,请访问PHP中文网!