作者简介:

       姜海强:闷骚码农,互联网行业摸爬滚打数余载,先后担任中国体育直播TV主程、网信集团先锋支付架构师、奇虎360服务器端资深开发。热爱技术,喜欢分享,热衷领域:PHP/Golang语言、面向对象设计模式、Redis、Yaf、Yii2、微服务等。

视频课程

yaf+yar微服务-腾讯课堂
yaf+yar微服务-51CTO学院
CSDN学院

Github

个人主页
swoole-boot
roach
roach-orm

QQ群:

姜海强的QQ群

公众号:

360tryst公众号

类自动加载

在编写面向对象程序时,每个类新建一个PHP文件,这会带来一个烦恼:每个脚本的开头,都需要require一个长长的列表。这就需要一种自动加载机制。

所谓类自动加载就是当我们想使用某个命名空间下的某个类时,直接use某个类,然后在使用这个类时自动按照某个规则将文件require,不用自己显示的require相应的代码文件。我们在使用一些开源框架时,一般都引入了类自动加载。

在PHP早期版本中通过__autoload()函数完成自动加载,在PHP5以后,官方推荐使用spl_autoload_register()函数实现类自动加载,spl_autoload_register()函数可以注册任意数量的自动加载器,当使用尚未被定义的类时自动去加载。

关于类自动加载也是有一定规范的,PSR-4规定了类自动加载的规范。

1. psr-4

PSR-4关于类自动加载的规范如下:

  • 1.The term “class” refers to classes, interfaces, traits, and other similar structures.
  • 2.A fully qualified class name has the following form:

    1. \<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>

    1.The fully qualified class name MUST have a top-level namespace name, also known as a “vendor namespace”.

    2.The fully qualified class name MAY have one or more sub-namespace names.

    3.The fully qualified class name MUST have a terminating class name.

    4.Underscores have no special meaning in any portion of the fully qualified class name.

    5.Alphabetic characters in the fully qualified class name MAY be any combination of lower case and upper case.

    6.All class names MUST be referenced in a case-sensitive fashion.

  • 3.When loading a file that corresponds to a fully qualified class name …

1.A contiguous series of one or more leading namespace and sub-namespace names, not including the leading namespace separator, in the fully qualified class name (a “namespace prefix”) corresponds to at least one “base directory”.

2.The contiguous sub-namespace names after the “namespace prefix” correspond to a subdirectory within a “base directory”, in which the namespace separators represent directory separators. The subdirectory name MUST match the case of the sub-namespace names.

3.The terminating class name corresponds to a file name ending in .php. The file name MUST match the case of the terminating class name.

  • 4.Autoloader implementations MUST NOT throw exceptions, MUST NOT raise errors of any level, and SHOULD NOT return a value.

2. 实现

因为作者是Yii2的严重用户,所以习惯性将命名空间和目录对应,且目录全部使用小写字母,一个符合PSR-4规范的自动加载类如下:

  1. /**
  2. * Class Autoload
  3. * @datetime 2020/6/29 11:27 上午
  4. * @author roach
  5. * @email jhq0113@163.com
  6. */
  7. class Autoload
  8. {
  9. private function __construct()
  10. {
  11. }
  12. private function __clone()
  13. {
  14. // TODO: Implement __clone() method.
  15. }
  16. /**
  17. * @var array
  18. * @datetime 2020/6/24 10:10 上午
  19. * @author roach
  20. * @email jhq0113@163.com
  21. */
  22. private static $_namespace = [];
  23. /**注册一个命名空间前缀
  24. * @param string $prefix
  25. * @param string $dir
  26. * @datetime 2020/6/24 10:10 上午
  27. * @author roach
  28. * @email jhq0113@163.com
  29. */
  30. public static function set($prefix, $dir)
  31. {
  32. self::$_namespace[ $prefix ] = $dir;
  33. }
  34. /**注册多个命名空间前缀
  35. * @param array $namespaceArray
  36. * @datetime 2020/6/24 10:14 上午
  37. * @author roach
  38. * @email jhq0113@163.com
  39. */
  40. public static function mset($namespaceArray = [])
  41. {
  42. foreach ($namespaceArray as $prefix => $dir) {
  43. self::$_namespace[ $prefix ] = $dir;
  44. }
  45. }
  46. /**
  47. * @param string $class
  48. * @datetime 2020/6/24 10:15 上午
  49. * @author roach
  50. * @email jhq0113@163.com
  51. */
  52. public static function autoload($class)
  53. {
  54. $position = strpos($class,'\\');
  55. $prefix = substr($class, 0, $position);
  56. if(!isset(self::$_namespace[ $prefix ])) {
  57. return;
  58. }
  59. $fileName = self::$_namespace[ $prefix ].str_replace('\\','/', substr($class, $position)).'.php';
  60. if(file_exists($fileName)) {
  61. require $fileName;
  62. }
  63. }
  64. }

在单入口应用当中,在你的入口文件index.php中添加如下代码即可完成自动加载。

  1. <?php
  2. //引入自动加载类文件
  3. require __DIR__.'/Autoload.php';
  4. //注册自动加载函数
  5. spl_autoload_register('Autoload::autoload');
  6. //注册命名空间前缀
  7. Autoload::set('library', dirname(__DIR__).'/library');

PHP依赖管理工具composer会自带一个符合PSR-4规范的类自动加载器,如果我们的项目是使用composer管理依赖的,我们可以直接使用composer的类自动加载器。

QQ群:

姜海强的QQ群

公众号:

360tryst公众号