博客列表 >PHP基础-名称空间/三种限定名称/空间和类的别名/类自动加载

PHP基础-名称空间/三种限定名称/空间和类的别名/类自动加载

岂几岂几
岂几岂几原创
2020年05月09日 15:12:50734浏览

命名空间

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

非限定名称

  • 从当前空间中访问当前空间中的成员, 可以省略当前空间名称. 即, 非限定名称: 成员之前的命名空间可省略
  • 不能有”\”, 可以理解成文件当前路径.

完全限定名称

  • 当需要访问其他命名空间下的成员时, 需要使用完全限定名称, 类似全局路径.
  • 必须以”\”开始.

非完全限定名称

  • 在成员前面出现了空间名称, 但是并不是从根空间开始, 就是非完全限定名称
  • 在命名空间之间有层级关系时, 如上级空间访问下级空间的成员时使用非完全限定名称.
  • 至少要有一个”\“, 且不能在首位, 可以理解成相对路径

全局成员的四大家族: 类, 接口, 函数和常量.

  1. namespace ns1 {
  2. require('../../out.php');
  3. class Demo1
  4. {
  5. public static $prop1 = 'hello';
  6. public static function func1()
  7. {
  8. return __METHOD__;
  9. }
  10. }
  11. // 在当前命名空间中使用本命名空间的成员, 可以省略当前空间名称, 即使用非限定名称即可.
  12. /* Demo1::$prop1 等效于 \ns1\Demo1::$prop1 */
  13. echobr(Demo1::$prop1);
  14. /* Demo1::func1() 等效于 \ns1\Demo1::func1() */
  15. echobr(Demo1::func1());
  16. /* result:
  17. hello
  18. ns1\Demo1::func1
  19. */
  20. }
  21. namespace ns2\ns2_1 {
  22. const PI = 3.14;
  23. class Demo1
  24. {
  25. public static $prop = 'hi';
  26. public static function func1()
  27. {
  28. return __METHOD__;
  29. }
  30. }
  31. }
  32. namespace ns2 {
  33. // 访问其他命名空间中的成员, 需要使用完全限定名称
  34. echobr(\ns1\Demo1::$prop1);
  35. echobr(\ns1\Demo1::func1());
  36. /* result:
  37. hello
  38. ns1\Demo1::func1
  39. */
  40. // 访问具有层级关系的下级命名空间中的成员时, 可以使用非完全限定名称
  41. echobr(ns2_1\Demo1::$prop);
  42. echobr(ns2_1\Demo1::func1());
  43. echobr(ns2_1\PI);
  44. /* result:
  45. hi
  46. ns2\ns2_1\Demo1::func1
  47. 3.14
  48. */
  49. }

2. 创建和使用命名空间

2.1 创建命名空间

  • 在同一个脚本中可以创建多个命名空间
  • 获取当前命名空间, 可以使用__NAMESPACE__.
  • 使用namespace关键字创建命名空间
  • 创建命名空间的语法

    • 创建语法 1:

      1. namespace 命名空间名称;
      2. // do something...

      这种方式只能创建命名空间, 不能创建匿名空间. 匿名空间就是默认空间, 根空间, 全局空间.

      1. /* 创建命名空间 */
      2. namespace ns1;
      3. // do something...
      4. /* 这样创建匿名空间会报错 */
      5. namespace ;
      6. // can not do something...
    • 创建语法 2:

      1. namespace 命名空间名称 {
      2. // do something...
      3. }

      这种方式可以创建命名空间和匿名空间

      1. /* 创建命名空间 */
      2. namespace ns1 {
      3. // do something...
      4. }
      5. /* 创建全局空间 */
      6. namespace {
      7. // 这里是全局空间
      8. }

2.2 使用命名空间

  • 对于函数和常量来说, 如果当前命名空间中不存在该函数或常量, PHP 会退而使用全局空间中的函数或常量.
  • 类名称总是解析到当前命名空间中的名称. 因此在访问系统内部或不包含在命名空间中的类名称时, 必须使用完全限定名称.
  1. /* 全局空间 */
  2. namespace {
  3. $username = '张三';
  4. function sayHello($username)
  5. {
  6. echobr('hello ' . $username);
  7. }
  8. class Demo
  9. {
  10. public static $prop = 'hello';
  11. }
  12. }
  13. /* 非全局命名空间 */
  14. namespace np1 {
  15. // 当前命名空间中并没有$username变量, PHP会到全局空间中去找该变量
  16. echobr($username);
  17. /* result: 张三 */
  18. // 跟变量类似
  19. sayHello('James');
  20. /* result: hello James */
  21. // 当前控件没有Demo类, 但PHP也不会到全局空间中查找, 直接报错
  22. echobr(Demo::$props);
  23. /* result: Fatal error: Uncaught Error: Class 'np1\Demo' not found in D:\phpstudy_pro\WWW\php11\PHP\0505\homework\homework.php:112 Stack trace: #0 {main} thrown in D:\phpstudy_pro\WWW\php11\PHP\0505\homework\homework.php on line 112 */
  24. }
  25. /* 命名空间中有跟根空间同名的成员 */
  26. namespace np2 {
  27. CONST NAME = 'lisi';
  28. function sayHello($username) {
  29. echobr('hi ' . $username);
  30. }
  31. class Demo {
  32. public static $prop = 'hi';
  33. }
  34. // 当前命名空间中已有相关成员的情况
  35. /* 使用当前命名空间中的常量 */
  36. echobr(NAME);
  37. /* 使用根空间中的同名常量 */
  38. echobr(\NAME);
  39. /* result:
  40. lisi
  41. 全局
  42. */
  43. /* 使用当前命名空间的函数 */
  44. sayHello('Marry');
  45. /* 使用根空间中的同名函数 */
  46. \sayHello('Lily');
  47. /* result:
  48. hi Marry
  49. hello Lily
  50. */
  51. /* 使用当前命名空间中的类 */
  52. echobr(Demo::$prop);
  53. /* 使用根空间中的同名类 */
  54. echobr(\Demo::$prop);
  55. /* result:
  56. hi
  57. hello
  58. */
  59. }

2.3 命名空间的别名

  • 在使用其他命名空间的成员时, 为简化完全限定名称的书写, 可以为使用的其他命名空间起别名.
  • 也可以为其他命名空间中的成员起别名。当别名跟成员名称相同时,可以省略别名。
  • 使用use关键字来声明空间别名. use默认从根空间开始. 使用as关键字来指定空间/成员别名。
  • 声明语法:

    1. /* 为名称空间起别名 */
    2. use 命名空间名称 as 别名名称;
    3. /* 为名称空间的成员其别名 */
    4. /* 1. 类 */
    5. use 省略第一个\的完全限定名称类名/非完全限定名称类名 as 别名名称;
    6. /* 或者 */
    7. use 省略第一个\的完全限定名称类名/非完全限定名称类名;
    8. /* 2. 函数 */
    9. use function ... as ...;
    10. /* 或者 */
    11. use function ...;
    12. /* 3. 常量 */
    13. use constant ... as ...;
    14. /* 或者 */
    15. use constant ...;

    示例:

    1. namespace ns1\test1 {
    2. class Demo {
    3. public static $username = '张三';
    4. }
    5. class Demo1 {
    6. public staitc $username = '李四';
    7. }
    8. }
    9. namespace ns2 {
    10. // 给命名空间起别名
    11. use ns1\test1 as nt1;
    12. // 给命名空间中的类起别名
    13. use ns1\test1\Demo1 as Demo1;
    14. // 当别名跟类名相同时, 可以省略别名
    15. use ns1\test1\Demo;
    16. // 使用别名简化调用
    17. echobr('姓名: ' . nt1\Demo1::$username);
    18. /* result:
    19. 李四
    20. */
    21. // 给类起别名
    22. echobr('姓名: ' . Demo1::$username);
    23. echobr('姓名: ' . Demo::$username);
    24. /* result:
    25. 姓名: 李四
    26. 姓名: 张三
    27. */
    28. }

3. 类的自动加载

实现类自动加载的条件

  1. 命名空间必须跟类文件的绝对路径一一对应。

  2. 当前类的名称必须跟当前文件的名称完全一致。

类自动加载的目的是要省略使用 require 引入各种文件。

一般把实现类自动加载的函数用系统函数 spl_autoload_register()函数进行注册。当代码中使用到未被加载的类时,PHP 会自动调用由 spl_autoload_register()函数注册的函数去尝试加载这个类。

类自动加载示例:

  1. autoload.php: 根据实现类自动加载的条件实现的自动加载函数,并使用 spl_autoload_register()函数进行注册。
  1. // autoload.php
  2. // 封装自动加载器
  3. try {
  4. // 系统函数: spl_autoload_register(): 注册执行加载类的函数
  5. spl_autoload_register(function ($className) {
  6. // 1. 将类名中的反斜线改为当前系统中的目录分隔符
  7. $path = str_replace('\\', DIRECTORY_SEPARATOR, $className);
  8. // echobr($path);
  9. // 2. 生成真正要加载的类文件名称
  10. $file = __DIR__ . DIRECTORY_SEPARATOR . $path . '.php';
  11. // echobr($file);
  12. // 3. 加载这个文件
  13. require $file;
  14. });
  15. } catch (Exception $e) {
  16. die($e->getMessage());
  17. }
  1. Demo1.php: 待加载的类文件
  1. // Demo1.php
  2. namespace tool;
  3. class Demo1 {
  4. public static function func1() {
  5. return __METHOD__;
  6. }
  7. public static function echobr($str = '') {
  8. echo $str . '<br>';
  9. }
  10. }
  1. work.php: 需要加载类实现业务逻辑的类
  1. namespace work;
  2. // 1. 加载自动加载器文件
  3. require('autoload.php');
  4. // 2. 使用use为待加载的类起别名
  5. use tool\Demo1;
  6. // 3. 使用待加载的类
  7. Demo1::echobr(Demo1::func1());
  8. /* 成功执行需加载类的方法,即自动加载生效。
  9. result: tool\Demo1::func1 */

4. 学习心得

  • 命名空间和三种限定名称,还是很容易理解的,可以认为是程序员把各种成员按照功能进行“归档”,当要用到这些成员时,顺着归档路径去加载即可。限定名称,是指在归档路径中的某个文件,要找到另外一个成员时,相对于该文件,或相对于归档根目录增加的路径。
  • 为命名空间或成员起别名,是为了简化使用其他命名空间的成员时的调用,或防止使用不同命名空间中的相同名字的成员时引起的冲突。
  • 类自动加载,在实际编写业务逻辑时较少用到,一般应用于框架的底层实现,是为了简化一些繁琐的文件或成员引用过程(如老师上课举的例子是为了简化加载类文件的引用过程)。
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议