Blogger Information
Blog 63
fans 8
comment 8
visits 50365
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
PHP大牛成长之路:命名空间与自动加载器
周Sir-BLOG
Original
708 people have browsed it

1、命名空间

1.1、理解全局成员

  1. // 全局成员共有四个: 函数, 常量, 类/接口(函数外部声明)
  2. // 1、函数
  3. function demo() {}
  4. // 2、常量
  5. const USER_NAME = 'Peter Zhu';
  6. // 3、类
  7. class User {}
  8. // 4、接口
  9. interface iDb {}
  10. // 全局成员最大特点:全局可见 / 最大缺点: 不能重复命名

1.2、命名空间的定义

1、命名空间使用 namespace 关键字定义,语法如下:

  1. namespace project1;
  2. namespace project2;
  3. namespace project3;

一般情况下,不推荐单个文件中定义多个命名空间,如果需要,可以使用大括号进行定义:

  1. namespace project1
  2. {
  3. }
  4. namespace project2
  5. {
  6. }
  7. namespace project3
  8. {
  9. }

1.3、命名空间的访问

非同一命名空间的访问,需指定要访问的命名空间名称
一旦定义命名空间,命名空间{}之外不能存在任何代码

  1. namespace project1
  2. {
  3. // 接口
  4. interface iTest {
  5. public function getSite();
  6. }
  7. // 类
  8. class Demo implements iTest
  9. {
  10. public function getSite()
  11. {
  12. return 'php中文网';
  13. }
  14. }
  15. // 函数
  16. function f1(iTest $obj) {
  17. return $obj->getSite();
  18. }
  19. // 常量
  20. const SITE_NAME='php中文网';
  21. //命名空间内访问:
  22. echo (new Demo)->getSite().'<br>';
  23. echo f1(new Demo).'<br>';
  24. echo SITE_NAME.'<br>';
  25. }
  26. //-------------------------------------------------------------
  27. // 注意:一旦定义命名空间,命名空间{}之外不能存在任何代码
  28. // echo (new Demo)->getSite().'<br>';
  29. // echo f1(new Demo).'<br>';
  30. // echo SITE_NAME.'<br>';
  31. //报错:Fatal error: No code may exist outside of namespace {}
  32. //-------------------------------------------------------------
  33. namespace project2
  34. {
  35. //在project2访问project1内容:
  36. echo '<hr>';
  37. //方法访问:示例化对象时加上要访问的命名空间名称
  38. echo (new \project1\Demo)->getSite().'<br>';
  39. //函数访问:函数前及示例化对象时都要加上要访问的命名空间名称
  40. echo \project1\f1(new \project1\Demo).'<br>';
  41. //常量访问:常量前加上要访问的命名空间名称
  42. echo \project1\SITE_NAME.'<br>';
  43. // “\”表示全局“路径”,相当于根目录位置开始
  44. }

1.4、命名空间使用

  • 非限定名称: 总是从全局空间开始, 前面总是一个: “\” , “\A\B…”

  • 限定名称:类名总是会有一个或多个空间名称,但不是从全局开始, “A\B…”

  • 完全限定名称:就是不带有空间名称的类,如当前命名空间的类。

  1. namespace project1
  2. {
  3. class T1 {}
  4. }
  5. namespace project2
  6. {
  7. class T1 {}
  8. }
  9. namespace project3
  10. {
  11. class T1 {}
  12. }
  13. namespace demo\project
  14. {
  15. class T1 {}
  16. }
  17. namespace demo
  18. {
  19. class T1 {}
  20. // 1. 完全限定名称的类名:\project1\T1 ,类似绝对路径
  21. echo \project1\T1::class, '<br>';
  22. echo \project2\T1::class, '<br>';
  23. echo \project3\T1::class, '<hr>';
  24. // 2. 限定名称的类名: demo\project 理解成相对路径(当前命名空间下的下一级可以省略当前命名空间)
  25. echo project\T1::class, '<hr>';
  26. // 3. 非限定名称的类:
  27. echo T1::class, '<hr>';
  28. }

1.5、命名空间的别名

  1. namespace project1
  2. {
  3. class T1 {}
  4. }
  5. namespace project2
  6. {
  7. class T1 {}
  8. }
  9. namespace demo
  10. {
  11. // 1、非别名访问
  12. echo \project1\T1::class, '<br>';
  13. echo \project2\T1::class, '<hr>';
  14. // 2、别名访问
  15. use \project1\T1 AS P1;
  16. use \project2\T2 AS P2;
  17. echo P1::class, '<br>';
  18. echo P2::class, '<hr>';
  19. }
  20. namespace demo1
  21. {
  22. class T1 {}
  23. // 3、如果当前类中也有一个与之同名的非限定的类,就不能省略别名
  24. use \project1\T1 AS PT1;
  25. echo PT1::class, '<br>';
  26. echo T1::class, '<hr>';
  27. }

2、类的加载

如demo.php目录下有以下几个类文件:

  1. #inc/lib/Test1.php
  2. // 当前类的命名空间与当前类的文件路径对应起来
  3. namespace inc\lib;
  4. // 类名必须与当前类文件名称相同
  5. class Test2 {}
  6. function show(){
  7. return 'PHP中文网';
  8. }
  9. #inc/lib/Test2.php
  10. namespace inc\lib;
  11. class Test2 {}
  12. #inc/lib/Test3.php
  13. namespace inc\lib;
  14. class Test3 {}

2.1、手动加载

  1. # demo.php
  2. require 'inc/lib/Test1.php';
  3. require 'inc/lib/Test2.php';
  4. require 'inc/lib/Test3.php';
  5. var_dump(new inc\lib\Test1());
  6. echo '<br>';
  7. var_dump(new inc\lib\Test2());
  8. echo '<br>';
  9. var_dump(new inc\lib\Test3());

如果一个php文件里需要引用更多对象,那么这个文件就需要使用include或require逐个引用,于是就可以使用自动加载。

2.2、自动加载

  1. # demo.php
  2. function classLoader($class)
  3. {
  4. // DIRECTORY_SEPARATOR 可以随操作系统不同,使用不同的目录分隔符
  5. //1、获取文件名(替换目录分隔符)
  6. // $path = str_replace('\\', '/', '\inc\lib\Test1' );
  7. $path = str_replace('\\', DIRECTORY_SEPARATOR, $class);
  8. //2、获取文件名完整路径(替换目录分隔符)
  9. $file = __DIR__ . DIRECTORY_SEPARATOR . $path . '.php';
  10. //3、检测文件是否存在,存在则引入
  11. if (file_exists($file)) {
  12. require_once $file;
  13. //equire()与require_once()的区别
  14. // require()会在每一处出现调用的地方都重新调用(加载文件)。
  15. // require_once() 指定的文件如果已经被包含过,则不会再次包含。它可以避免函数重定义,变量重新赋值等问题。
  16. }
  17. }
  18. try {
  19. spl_autoload_register('classLoader');
  20. }catch (Exception $e){
  21. die($e->getMessage());
  22. }
  23. var_dump(new inc\lib\Test1());
  24. echo '<br>';
  25. var_dump(new inc\lib\Test2());
  26. echo '<br>';
  27. var_dump(new inc\lib\Test3());
  28. //实例化对象可以使用use引用以缩短代码可读性
  29. use inc\lib\Test1;
  30. var_dump(new Test1());

使用匿名函数实现:

  1. try {
  2. spl_autoload_register(function($class){
  3. $path = str_replace('\\', DIRECTORY_SEPARATOR, $class);
  4. $file = __DIR__ . DIRECTORY_SEPARATOR . $path . '.php';
  5. if (file_exists($file)) {
  6. require_once $file;
  7. }
  8. });
  9. } catch (Exception $e) {
  10. die($e->getMessage());
  11. }
  12. // 通过实例化自动加载inc\lib\Test1.php
  13. new inc\lib\Test1();
  14. // 输出inc\lib\Test1.php中的函数
  15. echo \inc\lib\show();
  16. echo '<br>';
  17. var_dump(new inc\lib\Test1());
  18. echo '<br>';
  19. var_dump(new inc\lib\Test2());
  20. echo '<br>';
  21. var_dump(new inc\lib\Test3());

总结

1、全局成员共有四个: 函数, 常量, 类/接口(函数外部声明);
2、命名空间使用:namespace 空间名;namespace 空间名{}定义;
3、对命名空间的访问和使用有了初步理解;
4、类的加载需要includerequire手动引入类文件,使用spl_autoload_register()可以实现自动加载,通过验证,自动加载后函数也可以自动加载并访问。

Correcting teacher:天蓬老师天蓬老师

Correction status:qualified

Teacher's comments:以后要记得一个完整的类名应该是包括了空间名称的,如果没有, 就是当前空间
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
2 comments
老周 2020-08-02 21:26:42
我发现点回复没有用啊,老师都没评价,你就看出好了,哈哈哈
2 floor
老黑 2020-08-02 20:13:17
总结的很好啊,后面关注下
1 floor
Author's latest blog post