博客列表 >命名空间与类自动加载

命名空间与类自动加载

我是郭富城
我是郭富城原创
2020年05月06日 05:51:24681浏览

命名空间

1. 非限定名称, 限定名称, 完全限定名称

  • PHP 命名空间可以解决以下两类问题:
  • 用户编写的代码与 PHP 内部的类(接口)/函数/常量或第三方类/函数/常量之间的名字冲突。
  • 为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名(或简短)的名称,提高源代码的可读性。

    ::class获取类的完整名称(带上命名空间)

基础:命名空间的基本格式

  1. <?php
  2. // 定义代码在 'MyProject' 命名空间中
  3. namespace MyProject;
  4. // ... 代码 ...
  5. <html>
  6. <?php
  7. namespace MyProject; // 命名空间前出现了“<html>” 会致命错误 - 命名空间必须是程序脚本的第一条语句
  8. ?>
  9. </html>
  1. <?php
  2. //创建空间Nicola
  3. namespace Nicola;
  4. class Comment
  5. {
  6. }
  7. //非限定名称,表示当前Nicola空间
  8. //这个调用将被解析成 Nicola\Comment();
  9. $Nicola_comment = new Comment();
  10. //限定名称,表示相对于Nicola空间
  11. //这个调用将被解析成 Nicola\Article\Comment();
  12. $article_comment = new Article\Comment(); //类前面没有反斜杆\
  13. //完全限定名称,表示绝对于Nicola空间
  14. //这个调用将被解析成 Nicola\Comment();
  15. $article_comment = new \Nicola\Comment(); //类前面有反斜杆\
  16. //完全限定名称,表示绝对于Nicola空间
  17. //这个调用将被解析成 Nicola\Article\Comment();
  18. $article_comment = new \Nicola\Article\Comment(); //类前面有反斜杆\
  19. //创建Nicola的子空间Article
  20. namespace Nicola\Article;
  21. class Comment
  22. {
  23. }
  • 非限定名称,或不包含前缀的类名称,例如 $comment = new Comment();。如果当前命名空间是 Nicola\Article,Comment 将被解析为 Nicola\Article\Comment。如果使用 Comment 的代码不包含在任何命名空间中的代码(全局空间中),则 Comment 会被解析为 Comment
  • 限定名称,或包含前缀的名称,例如 $comment = new Article\Comment();。如果当前的命名空间是 Nicola,则 Comment 会被解析为 Nicola\Article\Comment。如果使用 Comment 的代码不包含在任何命名空间中的代码(全局空间中),则 Comment 会被解析为 Comment
  • 3.完全限定名称,或包含了全局前缀操作符的名称,例如 $comment = new \Article\Comment();。在这种情况下,Comment 总是被解析为代码中的文字名(literal name)Article\Comment

    其实可以把这三种名称类比为文件名(例如 comment.php)、相对路径名(例如 ./article/comment.php)、绝对路径名(例如 /blog/article/comment.php),这样可能会更容易理解。

2.实例演示: 命名空间的别名, 与类别名

  • PHP 命名空间支持 有两种使用别名或导入方式:为类名称使用别名,或为命名空间名称使用别名。
  • 在 PHP 中,别名是通过操作符 use 来实现的. 下面是一个使用所有可能的三种导入方式的例子
  1. <?php
  2. //a目录下的b
  3. namespace a\b {
  4. //a.php
  5. class A{
  6. function __construct(){
  7. echo "A in ".__NAMESPACE__;
  8. }
  9. }
  10. class B{
  11. function __construct(){
  12. echo "B in ".__NAMESPACE__;
  13. }
  14. }
  15. function foo(){
  16. echo "foo in ".__NAMESPACE__;
  17. }
  18. }
  1. <?php
  2. // a目录下的c
  3. namespace a\c {
  4. //b.php
  5. class B{
  6. function __construct(){
  7. echo "B in ".__NAMESPACE__;
  8. }
  9. }
  10. function f(){
  11. echo "foo in ".__NAMESPACE__;
  12. }
  13. }
  14. ?>
  1. <?php
  2. // a目录下面的c
  3. namespace a\c{
  4. //c.php
  5. include 'a.php';
  6. include 'b.php';
  7. use a\b\A as B,a\b\B as C;
  8. use function a\b\foo as f;
  9. f();//调用的是a\b\foo
  10. namespace\f();//调用的是a\c\f
  11. var_dump(new B());//创建的是a\b\A的对象
  12. var_dump(new namespace\B());//创建的是a\c\B的对象
  13. var_dump(new C());//创建的是a\b\B的对象
  14. }
  15. ?>

3. 实例演示: 类文件的自动加载器实现的原理与实现

  • 类的自动加载是指,在外面的页面中,并不需要去“引入”类文件,但是程序会在需要的时候动态加载需要的类文件。
  • 在 PHP 开发过程中,如果希望从外部引入一个class,通常会使用 includerequire 方法,去把定义这个 class 的文件包含进来。这个在小规模开发的时候,没什么大问题。但在大型的开发项目中,这么做会产生大量的 require 或者 include 方法调用,这样不因降低效率,而且使得代码难以维护,况且 require_once 的代价很大。
  • spl_autoload_register()此函数的功能就是把函数注册至 SPL 的autoload 函数栈中,并移除系统默认的autoload()函数
  1. <?php
  2. spl_autoload_register(function ($name) {
  3. include __DIR__ . '/autoload/' . $name . '.class.php';
  4. });
  5. $autoA = new AutoA();
  6. var_dump($autoA);

尽管 autoload()函数也能自动加载类和接口,但更建议使用spl_autoload_register()函数。 spl_autoload_register()提供了一种更加灵活的方式来实现类的自动加载(同一个应用中,可以支持任意数量的加载器,比如第三方库中的)。因此,不再建议使用 autoload() 函数,在以后的版本中它可能被弃用。

总结

本节课重点学习了命名空间的知识,在通常的 PHP 开发中,除了使用自己的代码以外,往往会使用很多其他的 PHP 组件。这些组件代码可能会使用相同的类名、接口名、函数或者常量名等,如果不使用命名空间就会导致命名冲突,使 PHP 执行出错。而将代码放到各自唯一的命名空间中,我们的代码就可以和其他开发者使用相同的类名、接口名、函数或者常量名等,这在团队合作中相当重要。

声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议