博客列表 >PHP 19 命名空间与类的加载(0729wed)

PHP 19 命名空间与类的加载(0729wed)

老黑
老黑原创
2020年07月31日 19:08:02510浏览

主要内容

  1. 全局成员
  2. 命名空间与对象访问
  3. 全局匿名空间
  4. 命名空间中的功能访问
  5. 类的加载(用spl_autoload_register的自动加载)

1. 全局成员

  1. <?php
  2. // 全局成员: 写在函数外部的东西
  3. // 全局成员有四个: 函数, 常量, 类/接口
  4. // 函数
  5. function demo() {}
  6. // 常量
  7. const USER_NAME = 'Peter Zhu';
  8. // 类
  9. class User {}
  10. // 接口
  11. interface iDb {}
  12. // 全局成员 最大的特点,全局可见
  13. // 全局成员的最大缺点: 不能重复命名
  14. class UserController {}
  15. class UserCenterController {}
  16. const USER_NAME_ROLE = 1;

2. 命名空间与对象访问

  1. <?php
  2. // 命名空间: 有名称的空间
  3. // 通过目录进行内部对象访问
  4. namespace one;
  5. // 接口
  6. interface iTest {
  7. public function getSite();
  8. }
  9. // 类
  10. class Demo implements iTest
  11. {
  12. public function getSite()
  13. {
  14. return 'php中文网';
  15. }
  16. }
  17. // 函数
  18. function f1(iTest $obj) {
  19. return $obj->getSite();
  20. }
  21. // echo (new Demo)->getSite();
  22. echo f1(new Demo);
  23. //////////////////////////////////////////////
  24. namespace two;
  25. // 在two空间中访问one空间的类
  26. // 使用:"\"表示全局空间,后面的类似一级一级的目录
  27. // echo (new \one\Demo)->getSite();
  28. // two\f1()
  29. echo \one\f1(new \one\Demo);
  30. // 当前语法,只能声明命名空间,而不能声明匿名空间/全局空间
  • 另外一种写法
  1. <?php
  2. namespace one
  3. {
  4. class Demo
  5. {
  6. public function getSite()
  7. {
  8. return 'php中文网';
  9. }
  10. }
  11. }
  12. ////////////////////
  13. namespace two
  14. {
  15. echo (new \one\Demo)->getSite();
  16. // echo '<hr>';
  17. // // 查看当前类全名
  18. // echo \one\Demo::class, '<br>';
  19. // class D {}
  20. // echo D::class;
  21. }

3. 全局匿名空间

  1. // 全局匿名空间
  2. namespace
  3. {
  4. // 因为有了全名空间, 那么全局成员的声明就不应该放在全局,而应该放在空间中
  5. // 全局空间应该主要写对全局对象的调用
  6. echo (new one\Demo)->getSite();
  7. }

4. 命名空间中的功能访问

  1. <?php
  2. // 在空间中访问类与访问函数有什么区别
  3. // 同名函数的调用
  4. namespace ns
  5. {
  6. // 访问类,不论是本空间的类,还是其它空间的类,都不能省略空间
  7. echo \Test::APP, '<hr>';
  8. function var_dump($name)
  9. {
  10. echo 'Hello 你调用的是我哟---' . $name;
  11. }
  12. /* 如果调用的函数与系统内置函数重名,则优先调用当前空间的函数
  13. 只有在当前空间找不到这个函数,再到全局中去查询
  14. 下面这种情况并没有调用系统内置的var_dump(),
  15. 而是调用了在当前空间自定义函数var_dump()
  16. */
  17. var_dump(\Test::APP);
  18. echo '<hr>';
  19. // 必须加上全局空间标识符: \, 才可以访问到系统内置的函数
  20. \var_dump(\Test::APP);
  21. }
  22. // 全局
  23. namespace
  24. {
  25. class Test
  26. {
  27. const APP = '我的博客';
  28. }
  29. }

5. 命名空间及内部对象的别名

  1. <?php
  2. // 命名空间的别名
  3. namespace ns1;
  4. class T1 {}
  5. namespace ns2;
  6. class T1 {}
  7. namespace ns3;
  8. // 从当前空间开始访问另一个空间, 应该从全局开始。三类方式
  9. // 1. 完全限定名称的类名:\ns1\T1 ,类似绝对路径
  10. echo \ns1\T1::class, '<hr>';
  11. // 访问ns3/sub::Hello
  12. // \ns3\sub\Hello:完全限定名称的类名
  13. // 类名可以省略掉与当前空间名称相当的部分
  14. // echo \ns3\sub\Hello::class;
  15. // 2. 限定名称的类名: sub\Hello, 理解成相对路径
  16. echo sub\Hello::class, '<hr>';
  17. class Work {}
  18. // 访问当前空间中的类,不要添加空间名称
  19. // 3. 非限定名称的类: Work
  20. echo Work::class, '<hr>';
  21. echo \ns2\T1::class, '<hr>';
  22. //-----------------------------------------
  23. // 使用空间或类名的别名来简化这种调用
  24. // 1. 空间级的别名: 给空间起个别名,使用关键字use
  25. // use 后面必须是一个完全限定名名称的空间或类
  26. use \ns2 as S;
  27. echo '别名访问: '. S\T1::class, '<hr>';
  28. // 2. 类级的别名, 给完全限定名称的类起个别名
  29. use \ns2\T1 as Test;
  30. echo '别名访问: '. Test::class, '<hr>';
  31. // 如果别名与类名相同,可以省略as以后面的别名
  32. // use \ns2\T1 as T1;
  33. use \ns2\T1 as TT;
  34. echo '别名访问: '. TT::class, '<hr>';
  35. // 以下情况必须使用别名
  36. // 如果当前类中也有一个与之同名的非限定的类,就不能省略别名
  37. class T1 {}
  38. namespace ns3\sub;
  39. class Hello {}
  40. // 完全限定名称: 总是从全局空间开始, 前面总是一个: "\" , "\A\B..."
  41. // 限定名称: 类名总是会有一个或多个空间名称,但不是从全局开始, "A\B..."
  42. // 非限定名称: 就是不带有空间名称的类 " User"

6. 类的加载

  1. <?php
  2. // 类的加载 - 从其他文件中加载进来
  3. require 'inc/lib/Test1.php';
  4. require 'inc/lib/Test2.php';
  5. require 'inc/lib/Test3.php';
  6. use inc\lib\Test1 as T1;
  7. use inc\lib\Test2 as T2;
  8. use inc\lib\Test3 as T3;
  9. echo T1::class, '<br>';
  10. echo T2::class, '<br>';
  11. echo T3::class, '<br>';
  • 目录及文件的访问
  1. <?php
  2. // 目录及文件的访问
  3. // __DIR__
  4. // echo __DIR__, '\\demo7.php';
  5. // require __DIR__ . '\\inc\\lib\\Test1.php';
  6. // echo \inc\lib\Test1::class, '<br>';
  7. // \inc\lib\Test1: 路径与空间对应
  8. // $path = str_replace('\\', '/', '\inc\lib\Test1' );
  9. $path = str_replace('\\', DIRECTORY_SEPARATOR, '\inc\lib\Test1' );
  10. echo $path;
  11. echo '<hr>';
  12. // echo __DIR__ . DIRECTORY_SEPARATOR . $path . '.php';
  13. require __DIR__ . DIRECTORY_SEPARATOR . $path . '.php';
  14. // echo Test1::class, '<br>';
  15. // 可以随操作系统不同,使用不同的目录分隔符
  16. // echo DIRECTORY_SEPARATOR;
  • 类的自动加载
  • 貌似有几个很2的规定,加载的php文件名需要等于其中class的名字。
  • 为了调取php中的函数,哪怕没有包括在class中,需要new下class,具体见作业部分。但其实用require的时候完全不用new class。
  1. <?php
  2. // 类的自动加载
  3. try {
  4. spl_autoload_register(function($class){
  5. $path = str_replace('\\', DIRECTORY_SEPARATOR, $class );
  6. $file = __DIR__ . DIRECTORY_SEPARATOR . $path . '.php';
  7. if (!(is_file($file) && file_exists($file)))
  8. throw new \Exception('不是文件名文件不存在');
  9. require $file;
  10. });
  11. } catch (Exception $e) {
  12. die($e->getMessage());
  13. }
  14. use inc\lib\Test1;
  15. use inc\lib\Test2;
  16. use inc\lib\Test3;
  17. echo Test1::class, '<br>';
  18. echo Test2::class, '<br>';
  19. echo Test3::class, '<br>';

7. 作业与实战

0729-作业

  1. 深刻理解三种类名称:完全限定,限定与非限定,并实例演示
  2. 写一个自动加载器,实现类的自动加载
    选做: 想一下这个加载器能否实现函数的自动加载?
  1. <?php
  2. //三种方式访问空间元素
  3. namespace liaoning\shenyang\tiexi\softpark;
  4. const USER = "jim";
  5. namespace beijing\haidian\xisanqi;
  6. const USER = "root";
  7. namespace liaoning\shenyang\tiexi;
  8. const USER = "admin";
  9. // ① 完全限定名称方式 访问元素 (类似 include('e:/web/0811/conf/common.php') 绝对路径引入文件)
  10. echo \beijing\haidian\xisanqi\USER,'<br><hr>'; //root
  11. // ② 限定名称方式 访问元素(不建议使用该方式) (类似 include('conf/common.php') 相对路径引入文件)
  12. //该方式元素: 当前空间+访问空间+具体元素;
  13. // liaoning\shenyang\tiexi\softpark\USER;
  14. echo softpark\USER,'<br><hr>';
  15. // ③ 非限定名称方式 访问元素 (类似 include('common.php') 相对路径引入文件)。同一目录下访问。
  16. echo USER; //admin
  1. <?php
  2. try{
  3. spl_autoload_register(
  4. function($class)
  5. {
  6. $path = str_replace('\\',DIRECTORY_SEPARATOR,$class);
  7. // 两个斜杠\\的意思,第一个为转意符,意思就是以\作为目录的拆分符。
  8. $file = __DIR__.DIRECTORY_SEPARATOR.$path.'.php';
  9. if (!(is_file($file) && file_exists($file)))
  10. throw new \Exception('不是文件,或者文件不存在');
  11. require $file;
  12. }
  13. );
  14. }catch(Exception $e){
  15. die($e->getMessage());
  16. }
  17. // 别名
  18. use inc\lib\test1; //前面的inc\lib是命名空间。
  19. use inc\lib\test2;
  20. use inc\lib\test3;
  21. echo Test1::class, '<br>';
  22. echo Test2::class, '<br>';
  23. echo Test3::class, '<br>';
  24. // 引入类文件
  25. new test1;
  26. new test2;
  27. new test3;
  28. // 引入类文件中的函数
  29. echo inc\lib\f1(),'<br>';
  30. echo inc\lib\f2(),'<br>';
  31. echo inc\lib\f3(),'<br>';
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议