批改状态:合格
老师批语:你的自动加载器, 应该能处理具有命名空间的完整类名, 修改一下
::class获取类的完整名称(带上命名空间)
基础:命名空间的基本格式
<?php// 定义代码在 'MyProject' 命名空间中namespace MyProject;// ... 代码 ...<html><?phpnamespace MyProject; // 命名空间前出现了“<html>” 会致命错误 - 命名空间必须是程序脚本的第一条语句?></html>
<?php//创建空间Nicolanamespace Nicola;class Comment{}//非限定名称,表示当前Nicola空间//这个调用将被解析成 Nicola\Comment();$Nicola_comment = new Comment();//限定名称,表示相对于Nicola空间//这个调用将被解析成 Nicola\Article\Comment();$article_comment = new Article\Comment(); //类前面没有反斜杆\//完全限定名称,表示绝对于Nicola空间//这个调用将被解析成 Nicola\Comment();$article_comment = new \Nicola\Comment(); //类前面有反斜杆\//完全限定名称,表示绝对于Nicola空间//这个调用将被解析成 Nicola\Article\Comment();$article_comment = new \Nicola\Article\Comment(); //类前面有反斜杆\//创建Nicola的子空间Articlenamespace Nicola\Article;class Comment{}
$comment = new Comment();。如果当前命名空间是 Nicola\Article,Comment 将被解析为 Nicola\Article\Comment。如果使用 Comment 的代码不包含在任何命名空间中的代码(全局空间中),则 Comment 会被解析为 Comment。$comment = new Article\Comment();。如果当前的命名空间是 Nicola,则 Comment 会被解析为 Nicola\Article\Comment。如果使用 Comment 的代码不包含在任何命名空间中的代码(全局空间中),则 Comment 会被解析为 Comment。$comment = new \Article\Comment();。在这种情况下,Comment 总是被解析为代码中的文字名(literal name)Article\Comment。其实可以把这三种名称类比为文件名(例如 comment.php)、相对路径名(例如 ./article/comment.php)、绝对路径名(例如 /blog/article/comment.php),这样可能会更容易理解。
<?php//a目录下的bnamespace a\b {//a.phpclass A{function __construct(){echo "A in ".__NAMESPACE__;}}class B{function __construct(){echo "B in ".__NAMESPACE__;}}function foo(){echo "foo in ".__NAMESPACE__;}}
<?php// a目录下的cnamespace a\c {//b.phpclass B{function __construct(){echo "B in ".__NAMESPACE__;}}function f(){echo "foo in ".__NAMESPACE__;}}?>
<?php// a目录下面的cnamespace a\c{//c.phpinclude 'a.php';include 'b.php';use a\b\A as B,a\b\B as C;use function a\b\foo as f;f();//调用的是a\b\foonamespace\f();//调用的是a\c\fvar_dump(new B());//创建的是a\b\A的对象var_dump(new namespace\B());//创建的是a\c\B的对象var_dump(new C());//创建的是a\b\B的对象}?>
class,通常会使用 include 和 require 方法,去把定义这个 class 的文件包含进来。这个在小规模开发的时候,没什么大问题。但在大型的开发项目中,这么做会产生大量的 require 或者 include 方法调用,这样不因降低效率,而且使得代码难以维护,况且 require_once 的代价很大。spl_autoload_register()此函数的功能就是把函数注册至 SPL 的autoload 函数栈中,并移除系统默认的autoload()函数
<?phpspl_autoload_register(function ($name) {include __DIR__ . '/autoload/' . $name . '.class.php';});$autoA = new AutoA();var_dump($autoA);
尽管
autoload()函数也能自动加载类和接口,但更建议使用spl_autoload_register()函数。spl_autoload_register()提供了一种更加灵活的方式来实现类的自动加载(同一个应用中,可以支持任意数量的加载器,比如第三方库中的)。因此,不再建议使用autoload()函数,在以后的版本中它可能被弃用。
本节课重点学习了命名空间的知识,在通常的 PHP 开发中,除了使用自己的代码以外,往往会使用很多其他的 PHP 组件。这些组件代码可能会使用相同的类名、接口名、函数或者常量名等,如果不使用命名空间就会导致命名冲突,使 PHP 执行出错。而将代码放到各自唯一的命名空间中,我们的代码就可以和其他开发者使用相同的类名、接口名、函数或者常量名等,这在团队合作中相当重要。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号