composer autoloader

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

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

1 什么是autoloading?

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

“烦人?”

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

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

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

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

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

2 创建一个autoloader

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

<?php
// Classes/A.php
class A {}
<?php
// Classes/B.php
class B {}
<?php
// index.php
include_once 'Classes/A.php';
include_once 'Classes/B.php';
// load A class
$a = new A();
// check the list of all loaded files
var_dump(get_included_files());

The script index.php will output:

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铛铛铛登场了:

<?php
// index.php
// 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()函数中编写了对类名及其文件路径进行“映射”的方式,并将其注册到脚本中,以便告诉脚本每次实例化类时,只需通过此函数查找它,加载它。

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

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:

{
  "autoload": {
    "classmap": [
      "Classes/"
    ]
  }
}

更新index.php:

require __DIR__ . '/vendor/autoload.php';

$a = new A();

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

return array(
  'A' => $baseDir . '/Classes/A.php',
  'B' => $baseDir . '/Classes/B.php',
);

都是从下面一行开始的

require __DIR__.'/../vendor/autoload.php';

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

// \Composer\ComposerAutoloaderInitXXXX:getLoader()
public static function getLoader() {
  ...
  // \Composer\ClassLoader::register()
  $loader->register(true); 
return $loader;
}

这里就是注册autoloader的地方

// \Composer\ClassLoader::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(); 会加载如下:

<?php
// path /Classes/A.php
class Classes_A {}

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

  • composer.json运行时,任何命名空间前缀App将在Classes目录中查找该文件,但是使用psr-0,你会发现它无法按预期工作:
{
  "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

本文分享自微信公众号 - 佳爷的后花媛(zoe1368329355),作者:仇诺伊

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-08-24

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 关于TCP/IP的面试题

    包含HTTP TCP IP的一些面试题,解答可能不够详细和准确,如有错误,还望指出,仅供参考。

    仇诺伊
  • MNMP (Mac + Nginx + MySQL + PHP) 开发环境搭建

    ruby -e "$(curl --insecure -fsSL https://raw.githubusercontent.com/Homebrew/inst...

    仇诺伊
  • 今日推荐:examples-of-web-crawlers

    今天推荐一些非常有趣的python爬虫例子,对新手比较友好,主要爬取淘宝、天猫、微信、豆瓣、QQ等网站。(Some interesting examples o...

    仇诺伊
  • Blockchain:Internet问世以来最具破坏力的发明

    您可能听说过比特币(Bitcoin)、或许也听过一种叫做「区块链」(blockchain)的网路钱包技术;但您或许不知道,blockchain不只会抢走银行、证...

    ImportSource
  • Mac上自己推送iOS通知到设备

    打开“终端(terminal)”,然后(注意,sudo需要的密码就是系统的root帐号密码)运行“sudo apachectl start”

    用户6094182
  • 自己部署 PHP 版本的 Wafer2 Demo

    自行部署适用于想将腾讯云 Wafer SDK 和 Demo 部署在自己的服务器上以获得更高的灵活性和操纵权限的用户。部署过程需要从零开始搭建线上环境,需要有一定...

    Jason
  • python的requests模块实现登

    -- coding:utf-8 -- import requests import re

    py3study
  • 悬赏题No.1 - 扑克牌

    ACM算法日常推出悬赏题啦,悬赏题一般是平时日常听闻的题目,题意简单,结构稍微复杂,并且不知道算法的结果,需要解题者在理解题意的情况下给出合理的解决方案和结果...

    ACM算法日常
  • LinkedHashSet 源码分析

    LinkedHashSet 源码分析 1. 在阅读源码时做了大量的注释,并且做了一些测试分析源码内的执行流程,由于博客篇幅有限,并且代码阅读起来没有 IDE ...

    lwen
  • Spring MVC 你必须关注点

    Spring MVC配置简单,特别是在SpringBoot出现后基本都是开箱即用。在实际项目中通常是需要单独去处理一些特殊的情况,比如统一的异常处理,校验器以及...

    李鸿坤

扫码关注云+社区

领取腾讯云代金券