Drupal8开发者必备的5个PHP组件之一:Composer

Drupal 8作出了很大的变化,架构上的,技术上的变化比比皆是,但是Drupal8同时也改变了Drupal社区。我们现在还不能感受到这些变化所带来的全部影响,但是随着时间的推移,我相信Drupal8新的发展方向将会为我们的社区带来非常好的影响。这些变化中一个重要的组成部分就是决定采用外部代码。这是一个180度的转变,从NIH(非我所创)文化变为PFE/PIE(为在别的地方发现感到自豪,为别人已经发明了感到自豪)文化,这真是一件让人震惊和戏剧化的一个改变。我们这些Drupal从业者正在这场变革当中感受着其中的变化,这个系列文章将会给你一个利用这些变化的不错的起点。

但Drupal不是唯一一个发生变化的系统,PHPBB, EZPublish甚至是一些非产品的PHP系统都开始了跟进PHP文化的改变。这被一些人称作是“PHP的复兴”,互操作性是这场变革的驱动力,并且在一些因素的作用下已经开始变为现实,这些因素包括:

  • PHP 5.3的命名空间机制,以及面向对象方面能力的增强
  • PHP 框架互操作小组(PHP-FIG)发布了类自动加载机制的规范,包括PSR-0PSR-4
  • 一个叫做Composer的工具的及时出现

Composer其核心是一个依赖管理工具,但是其将网上不同来源的PHP组件组合成一个连冠的整体的能力让其对现代PHP开发者来说是必不可少的工具。在这篇文章里,我们将会深入到Composer的基础知识,讨论它能为我们做什么,怎么去用以及一些让人激动的特性。

安装

安装Composer是非常简单直观的,不同*nix发行版和Windows的安装说明可以在这里找到:

*nix安装
Windows安装

我推荐使用全局安装方式,当然为每个项目单独安装是完全能够做到的,但大多数情况下都不是那么理想。

基本概念

一旦你安装了Composer,你就能迅速的开始使用它,让我们进入htdocs目录,创建一个新的目录。

cd /path/to/htdocs
mkdir composer_test

一旦你有了一个用来折腾Composer的目录,下一步就是创建和编辑composer.json文件。

vim composer.json

composer.json文件最基本的用法是声明在你的PHP项目中希望使用的各种代码组件。如果你熟悉Drush make,你会感觉到有非常熟悉且陌生的感觉。如果你不熟悉Drush make也不要担心,我们将在本文中详细介绍里面的每个步骤。

为了声明对某一个组件的依赖,你需要知道组件的名字。在我们的例子中,我们将要依赖一个流行的组件,叫做Guzzle。你可以把下面的代码复制到composer.json文件,然后保存。

{
    "require": {
       "guzzlehttp/guzzle": "4.0.*"
    }
}

如果你不熟悉JSON,这是一个数组的定义,在这个数组中声明了对一个组件的依赖。当前我们依赖的是来自于guzzlehttp库的4.0.x版本的guzzle核心组件。然后保存并退出composer.json文件。

特别提示:Composer也提供了一个composer init命令,让你可以通过一个向导建立你的composer.json文件。这种方法涉及到的一些细节不在本教程的讨论范围,所以我们没有使用,而是作为一个提示,告诉你composer内置的更多的优点。

我们已经建立了composer.json文件,现在我们可以执行最让人激动的任务了,即自动得到这些我们依赖的组件的代码,这里我假设你已经全局安装了composer,如果不是全局安装,你可能需要用php composer.phar替代composer命令,在composer.json同级目录运行:

composer install

Composer将会对一个叫做packageist的网站发起一个请求,packageist的作用是找到其他PHP组件。其将会找到任何composer.json文件里声明的组件,并把他们下载到一个新建的vendor目录。因为我们指定了版本是4.0.x版本,所以将会从4.0分支上下载最新发布的代码。另外,Composer还会在composer.json文件的同级目录生成一个composer.lock文件。

和Drush make不同的是,Composer实际上做了一个额外的操作,用锁定文件(lock file)来保护我们和我们的合作者。如果你以前用过Drush make,指定一个具体的模块版本是一个被鼓励使用的最佳实践。这样做的目的是让你的模块版本和你的团队成员的安装的模块版本总是一致的。当你在composer里指定一个组件具体的版本号时,锁定文件里将明确的记录你下载的具体的版本号,这样可以确保其他开发者下载的也是同样的版本号,这意味着要想使用更新版本的组件,必须有意的去更新锁定文件里的组件版本号,并提交到版本库中(译者注:意味着在你提交之前你测试过,更新的组件版本也是与你的项目兼容的)。这是一个非常值得的步骤,因为更新你的组件代码版本是非常重大的事件,需要让整个团队都知道,不应该让其隐式的发生。这是Composer的重要特性之一,而且其常常被忽视和误解。

到这儿,你应该已经让guzzle组件安装在了vendor目录,现在让我们研究一下我们刚刚得到的是什么。

cd vendor/guzzlehttp
ls -l

你应该有2个目录,guzzle和streams。这看起来有点奇怪,因为我们只让下载guzzle了,让我们在深入研究一下。

cd guzzle
ls -al

第一件要注意的事情就是,这里也有一个composer.json文件,让我们看看里面有什么。

vim composer.json

这个文件里有不少的内容,都是关于依赖关系的一个列表,如果我们看依赖数组,首先我们会看到组件依赖于PHP 5.4+版本,并且依赖于1.x版的guzzlehttp/streams。这解释了为什么在vendor/guzzlehttp里多出了一个streams目录。

在这个文件里,另一件值得注意的事情是我们刚刚下载的是MIT开源协议的文件,其有名字和描述,一些关键词,一些自动加载说明。如果你熟悉Drupal模块的.info机制(Drupal8里是.info.yml),这将会让你觉得非常眼熟。虽然这里可以花一些时间一个一个过一遍每个元素的作用,但我是决定把这个作为给读者留的一个课后练习。

值得一提的是,Composer不仅仅是一个依赖管理和组件下载工具,其也创建并管理一个非常有用的类加载器,让我们看看composer已经为我们做了什么。在vendor目录你会注意到有一个vendor文件夹,看看里面有什么。

cd vendor/composer
ls -al

Composer dir

这里能看到有许多文件。其中前两是希望能够让你重视的,它们是ClassLoader.php和autoload_real.php。我们不准备深入说明,只是要指出他们主要负责的是自动加载流程。(这里有一段译者没有详细翻译,大体意思是这里的每一个文件在自动加载流程都有特殊的作用。)

autoload_*.php文件每一个的作用如下:

  • files: 一系列文件,包含了带命名空间的函数,这在composer.json里有一定的说明。
  • namespaces: 一组符合PSR-0命名规范的目录,目前是空的。
  • psr4: 一组符合PSR-4命名规范的目录,这里是非空的,因为Guzzle使用了这个规范。
  • classmap: 一组类名对应的文件路径,目前也是空的。

这一点很有趣,我们能够迅速的知道一些事情,仅仅是通过看这些文件的内容。

Guzzle使用PSR-4自动加载标准,因此Guzzle在对应文件中有一些带命名空间的函数和一些类。

当我们混合使用多个项目时,这些文件填充的会越来越多,然而我想要让你引起注意的是类映射部分,因为这是composer的一个非常有用的特性。为了获得最快的自动加载的体验,你需要一个类映射,Composer可以帮你构建一个。这个流程本质上是发现每个类以及相关的文件,并且为了使用一个类,在调用时简单的包含进来。Composer不会开箱即用的为所有的类生成类映射,但我们可以通过一个命令来生成,每次你添加了一个新的组件到你的项目,你可能需要再次执行这个命令。(命令需要在composer.json的同级目录生成)

composer dump-autoload -o

执行了上面的命令之后,你可以:

vim vendor/composer/autoload_classmap.php

你将会看到类似于这样的内容:

Classmap

这是一个你的代码中每个组件类的列表(除了Composer自己的类)。如果你想让这些类自动加载,只需要:

// This will initialize composer’s autoloader
$loader = require_once __DIR__ . '/vendor/autoload.php';
// Instantiates a new guzzle client.
$client = new GuzzleHttp\Client(); 

这将会产生一个新的Guzzle客户端。

特别提示: 类映射自动加载器应该仅被用于生产服务器,在开发阶段如果你在自己的自定义组建里积极的创建,重命名,删除类,你可能需要经常重建你的类映射文件。

从Drupal的角度,这非常好因为我们不再需要为了让类自动加载,将类所在文件添加到*.info文件,我们已经使用了和其他PHP框架一样的标准化的类加载方式。模块目前同时支持PSR-0和PSR-4类自动加载,这非常的强大,因为这打开了一扇门,让更多的外部代码可以很容易的在Drupal中使用,并且在未来,也许让Drupal的模块代码也能让其他框架使用。

还有许多非常好的Composer特性这篇博文没有提及,但是在接下来的文章中,我们会继续使用Composer构建我们的示例项目。希望Composer能够成为你未来项目中的一大助力。

作者:Kris Vanderwater
译者:理查