composer autoloader

2020-04-23 17:53:59 浏览数 (1)

大家都知道composer吧,它是 PHP 用来管理依赖(dependency)关系的工具。你可以在自己的项目中声明所依赖的外部工具库(libraries),Composer 会帮你安装这些依赖的库文件。

今天不是说composer的,是关于如何管理由composer加载的大量packages。

1 什么是autoloading?

“喵喵,你觉得写一长串需要包含的文件放在脚本的开头,是不是很烦人的事?”

“烦人?”

“如果你在开发一个应用,你发现你有一长串需要加载的库,你会怎么做?”

“直接把这些库放到文件中,这样想用哪个就用哪个了”

“这就很烦人了啊,如果里面有你暂时不需要用的,但是你放进去了,不觉得占地方么?当你想用哪个类库就放哪个进去,不觉得更方便么?”

“好像是哦,那怎么去实现呢?”

“这就是autoloading,来,为夫和你说说”

2 创建一个autoloader

“按照你说的,把所有的文件都放进去”

代码语言:javascript复制
<?php
// Classes/A.php
class A {}
代码语言:javascript复制
<?php
// Classes/B.php
class B {}
代码语言:javascript复制
<?php
// index.php
include_once 'Classes/A.php';
include_once 'Classes/B.php';
代码语言:javascript复制
// load A class
$a = new A();
代码语言:javascript复制
// check the list of all loaded files
var_dump(get_included_files());

The script index.php will output:

代码语言:javascript复制
array(3) {
  [0]=> string(20) "/path/to/root/index.php"
  [1]=> string(24) "/path/to/root/Classes/A.php"
  [2]=> string(24) "/path/to/root/Classes/B.php"
}

无论有没有用到B,我们把所有的都放进去了,当你后面项目越来越大,文件越来越多,就会gg了。

这时候autoloading铛铛铛登场了:

代码语言:javascript复制
<?php
// index.php
代码语言:javascript复制
// my custom autoloader
function my_autoloader($class) {
  include 'Classes/' . $class . '.php';
}

// register the autoloader
spl_autoload_register('my_autoloader');
//spl_autoload_register — 注册给定的函数作为 __autoload 的实现

// load A class
$a = new A();

// check the list of all loaded files
var_dump(get_included_files());

你在my_autoloader()函数中编写了对类名及其文件路径进行“映射”的方式,并将其注册到脚本中,以便告诉脚本每次实例化类时,只需通过此函数查找它,加载它。

所以,现在检查脚本中加载的文件数:

代码语言:javascript复制
array(2) {
  [0]=> string(50) "/path/to/demos/autoload-2/index.php"
  [1]=> string(54) "/path/to/demos/autoload-2/Classes/A.php"
}

这时候你就载入了你想用的了。

PHP会告诉你“即使你没有在$ a = new A()之前加载它,它也会给你机会去加载你的类。在那之后,如果它不起作用,我将抛出异常“。

attention:

1 文件名应该具有相同的类名

2 每个文件应该都只有一个类

3 注意文件名和类名不要和其他冲突

3 composer如何进行自动加载

添加composer.json:

代码语言:javascript复制
{
  "autoload": {
    "classmap": [
      "Classes/"
    ]
  }
}

更新index.php:

代码语言:javascript复制
require __DIR__ . '/vendor/autoload.php';

$a = new A();

使用classmap,告诉composer这是做映射的方法,细节的话可以看运行composer install后vendor / composer / autoload_classmap.php :

代码语言:javascript复制
return array(
  'A' => $baseDir . '/Classes/A.php',
  'B' => $baseDir . '/Classes/B.php',
);

都是从下面一行开始的

代码语言:javascript复制
require __DIR__.'/../vendor/autoload.php';

ComposerAutoloaderInitXXXX:getLoader() 会在最后自动注册加载器。

代码语言:javascript复制
// ComposerComposerAutoloaderInitXXXX:getLoader()
public static function getLoader() {
  ...
  // ComposerClassLoader::register()
  $loader->register(true); 
return $loader;
}

这里就是注册autoloader的地方

代码语言:javascript复制
// ComposerClassLoader::register()
public function register($prepend = false) {
  spl_autoload_register(array($this, 'loadClass'), 
  true, $prepend);
}

无论啥时实例一个类,都会通过 ClassLoader::loadClass() 去寻找相应的类并加载。

4 类映射与PSR-0与PSR-4的对比。

这里有很多不同的类映射方式,一旦使用其中一种,就要遵循规则,composer会根据遵循的去查找和加载。

a) Classmap:最简单,在vendor / composer / autoload_classmap.php中,当composer自动加载类时,它扫描所提到目录中的所有文件(在composer.json文件中) 并创建一个名称空间数组和相应的路径。

注意:添加新文件需要使用composer dumpautoload重新生成。

b) PSR-0: 当这个逻辑存在在 vendor/composer/autoload_namespaces.php, 要遵循PSR-0规则.

c) PSR-4: 当存在在 vendor/composer/autoload_psr4.php, 要遵循 PSR-4.

PSR-0 和 PSR-4 的规则大致相同。

注意:

  • 对于这两者,每次添加新的PHP类时都不必运行composer dumpautoload,因为“搜索文件路径”过程是动态进行的。
  • 必须使用名称空间,尤其是PSR-4,因为名称空间附加到文件路径。
  • 子目录名称必须与子命名空间名称的大小写匹配。-PSR-4
  • PSR-0将下划线转换为目录分隔符,而它不在PSR-4中:

每个 "_" in the CLASS NAME 被转换成 a DIRECTORY_SEPARATOR. The "_" character 并没有特殊含义. -PSR-0

所以 $a = new Classes_A(); 会加载如下:

代码语言:javascript复制
<?php
// path /Classes/A.php
class Classes_A {}

注意L这里没有用到命名空间:

  • composer.json运行时,任何命名空间前缀App将在Classes目录中查找该文件,但是使用psr-0,你会发现它无法按预期工作:
代码语言:javascript复制
{
  "autoload": {
    "psr-4": {
      "App\" : "Classes"
    }
  }
}

5 参考

  1. http://php.net/manual/en/function.spl-autoload-register.php
  2. https://www.php-fig.org/psr/psr-4

虽然不能来场说走就走的旅行,但是有很多说看就看的图片

Basic

基础

数组函数

array_fill_keys — 使用指定的键和值填充数组

array_fill — 用给定的值填充数组

array_filter — 用回调函数过滤数组中的单元

array_flip — 交换数组中的键和值

array_intersect_assoc — 带索引检查计算数组的交集

array_intersect_key — 使用键名比较计算数组的交集

array_intersect_uassoc — 带索引检查计算数组的交集,用回调函数比较索引

array_intersect_ukey — 用回调函数比较键名来计算数组的交集

array_intersect — 计算数组的交集

Learning

English

Last year Mitsuo Setoyama, who was then education minister, raised eyebrows when he argued that liberal reforms introduced by the American occupation authorities after World War II had weakened the "Japanese morality of respect for parents."

end

0 人点赞