在过去,保持基于包的PHP项目是最新的是一个巨大的挑战。我们有像PEAR和PECL这样的软件包管理器,但它们经常引发更多挑战,而不是提供快速安装和管理软件包的便利。幸运的是,随着作曲家解决困难,所提到的管理者的黑暗时代现在已成为历史。Composer已经针对每个新版本进行了改进,许多现代平台/框架如Symfony,Laravel和Magento都使用Composer作为其系统的一部分。
Composer允许您声明所需软件包及其依赖项的列表,并自动执行软件包安装或使升级过程更容易。但是,老实说,包管理器的配置和功能可能不容易理解,特别是在开始时。
Composer有两种类型的配置文件:composer.json和composer.lock。JSON配置文件包含在主项目以及每个特定包中。简而言之,Composer应该知道要安装什么以及从哪些来源安装。此信息在主项目的JSON配置文件中声明。同时,每个包都有自己的要求(依赖关系,平台版本)。软件包的JSON配置文件包含有关上述要求的信息。该composer.lock配置文件只为主营项目是实际的。特定包不包含此配置文件。
那么,为什么我们需要两个不同的配置文件,composer.lock文件的目的是什么?让我们假设我们已经创建了一个基于包的项目。我们确保我们的项目适用于包foo_v1.5.1和包bar_v.2.2.6。但是,一旦新的软件包版本发布,我们也希望将来有可能为我们的项目升级这些软件包。因此,在我们composer.json文件中,我们可以声明所要求的包版本foo_v1.5。*(这意味着> = 1.5和<1.6)。但是,我们目前还不能确定,我们的项目将与foo_v1.5.2工作,因为它尚未公布,我们有没有机会与新的软件包版本来测试我们的项目。这就是为什么我们不允许Composer在我们的项目安装时安装最新版本的软件包。在这里composer.lock文件可以作为生命保护程序使用。此时,“.lock”扩展名变得不言自明。使用.lock文件,我们可以从字面上锁定项目的确切包版本。幸运的是,我们不必手动创建锁文件。它将在运行composerupdate
命令后由Composer自动创建。
Composer“新手”的下一个障碍是命令composer install
和composer update
命令之间的区别。首先,只有当项目中存在composer.lock文件时,install命令才可用。基本上,包管理器忽略composer.json中的所有记录配置安装命令。安装命令将从锁定文件中收集所有信息,并安装在此文件中声明的确切包版本。但是,如果我们声明版本后缀为星号–foo_v1.5。*,Composer如何知道确切的版本?如果使用通配符或版本范围声明版本,则Composer将在锁定文件中创建相应的记录,该记录等于当前可用的与规则匹配的最新版本。因此,如果foo_v1.5包的最新版本是1.5.6,则Composer将在composer.lock文件中为此版本创建一条记录。这就是composer update
命令发生的地方。
update命令生成带有精确版本软件包的composer.lock文件,如前所述,并运行composer install
命令安装所有软件包。现在让我们来谈谈陷阱。从存储库中提取基于Composer的项目时,您肯定可以运行该composer install
命令。在大多数情况下,如果您的系统满足所有要求,您将成功安装项目。不过,你应该小心composer update
命令。您可以猜测,此命令会重新生成锁定文件,您可能安装了从未使用当前版本的项目测试过的软件包版本。如果你足够幸运并且项目开发人员明智地使用版本范围,可能你仍然会有工作项目,也许还有一些小错误。但通常情况会变得更糟。
Composer的一个很棒的功能是它自己的自动加载器。使用包管理器,我们不需要大量的声明或SPL自动加载注册。Composer通常使用PSR-4自动加载,并且还支持PSR-0自动加载。这些可怕的缩写只是在PHP项目范围内的名称空间声明的一组标准。require('here/is/a/long/path/to/the/file')
现在让我们深入研究Magento 2应用程序范围内的composer.json文件结构。通过在文本编辑器中打开提到的文件,您将看到以下配置:
1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | { "name": "magento/magento2ce", "description": "Magento 2 (Community Edition)", "type": "project", "version": "2.2.0-dev", "license": [ "OSL-3.0", "AFL-3.0" ], "require": { "zendframework/zend-stdlib": "~2.4.6", "zendframework/zend-code": "~2.4.6", … }, "require-dev": { "phpunit/phpunit": "4.1.0", "squizlabs/php_codesniffer": "1.5.3", "phpmd/phpmd": "@stable", … }, "replace": { "magento/module-marketplace": "100.2.0-dev", "magento/module-admin-notification": "100.2.0-dev", "magento/module-advanced-pricing-import-export": "100.2.0-dev", "magento/module-analytics": "100.2.0-dev", "magento/module-authorization": "100.2.0-dev", … }, "extra": { "component_paths": { "trentrichardson/jquery-timepicker-addon": "lib/web/jquery/jquery-ui-timepicker-addon.js", … } }, "autoload": { "psr-4": { "Magento\\Framework\\": "lib/internal/Magento/Framework/", "Magento\\Setup\\": "setup/src/Magento/Setup/", "Magento\\": "app/code/Magento/" }, "files": [ "app/etc/NonComposerComponentRegistration.php" ] }, "autoload-dev": { "psr-4": { "Magento\\Sniffs\\": "dev/tests/static/framework/Magento/Sniffs/", … } }, "minimum-stability": "alpha", "prefer-stable": true } |
1 |
第一行包含有关项目的元信息。Composer存储库使用它来获取有关包和项目的一般信息。在该require
部分中,列出了具有指定版本的当前项目所需的包。正如我们之前提到的,软件包版本可以表示为确切的版本号,也可以使用不同的模式来选择可能的版本号范围。有关模式的更多信息可以在 官方的Composer文档中找到。该require-dev
部分非常类似于require
部分。它包含所需包的列表,但适用于开发环境。默认情况下,将安装本节中列出的所有软件包。我们可以通过在install或update命令中添加参数来禁用开发包安装。--no-dev
如果需要安装某些第三方软件包,则足以在该require
部分中声明软件包名称和软件包版本。Composer还有一个单独的require
命令,允许自动将包添加到composer.json文件的相应部分。对于上面示例中的Zend Framework模块,添加包的命令将具有以下结构:
1 | composer require zendframework/zend-code ~2.4.6 |
该replace
部分包含一个包列表及其开箱即用的当前项目或包中已存在的版本。因此,如果其他软件包需要此列表中的某些内容,则Composer会检查此部分中的软件包列表,并且不会查找远程存储库中列出的软件包列表。
该extra
部分包含使用以下命令可以访问的任意数据:
1 | $composer->getPackage()->getExtra() |
PHP对象$composer
的实例在哪里Composer
。
这些autoload
和autoload-dev
部分负责相应地自动加载生产和开发环境的配置。软件包管理器使用自己的自动加载器在系统中的所有软件包之间建立连接。
当为部分中的特定包设置版本范围而不是确切版本时,minimum-stability
和prefer-stable
参数会影响首选包require
的版本。
在Magento 2 Commerce中,由于安装的特殊性,根composer.json文件存在一些差异。主要区别在于没有任何replace
部分。所有包都在名为的meta包中注册magento/product-enterprise-edition
。该软件包包含require
所有Magento组件的部分。一些包的远程源也不同。
还有一个部分repositories
只有一个记录:
1 2 3 4 5 6 | "repositories": [ { "type": "composer", "url": "https://repo.magento.com/" } ] |
此部分包含Composer将查找包的存储库列表。在Magento 2开源中我们没有这样的部分。如果没有为项目设置存储库部分,Composer将在默认的Composer存储库中查找包 – https://packagist.org/
composer.json文件中列出的包通常包含一个名为的参数type
,该参数用于包的自定义安装逻辑。默认包类型是library
。对于库包,Composer只是将文件复制到供应商目录。在Magento 2中有5种与自定义平台相关的包类型:
- magento2模块
- magento2主题
- magento2库
- magento2语言
- magento2组分
所有这些软件包都由Magento Composer安装程序扩展程序处理,该扩展程序随Magento 2一起提供。该扩展是一个Composer插件,为上面列出的Magento 2软件包提供安装程序。安装程序是作为\MagentoHackathon\Composer\Magento\Plugin
类实现的,包含用于处理不同包类型的逻辑。
基本上,包类型之间的主要区别是安装目录。您可以在MagentoHackathon\Composer\Magento\PackageTypes
类中找到每个包的安装目录列表。
我希望本文中的信息能够帮助您更好地理解Magento 2范围内的Composer流程和配置,避免导致花费数小时的常见错误,以找出“不可预测”的Composer出了什么问题。谢谢阅读。