Composer简易教程文字版

1,113 阅读31分钟
原文链接: www.learn-tips.com
阿北也亲自录制了视频版,感兴趣的可以免费领取 《Composer视频手册》视频课程

一个更加包容和宽泛的Composer

逻辑是不复杂的,这货就是帮我们管理扩展及其依赖关系。

比如我在开发一个php网站,突然需要二维码生成功能,自己写太麻烦,这个时候我可以去composer的扩展列表里看一看,如果有直接下载下来用就可以了,当然可能这个扩展还需要另外一个扩展或库。

而我们不用担心这个,composer能帮我们下载二维码生成扩展及它所需要的各种库直至正常运行。

这就是管理扩展及其依赖关系。Composer是个很贴心的家伙。

老大哥的接班人

在Composer诞生约10年前,就是2000年的PHP开发者会议上有个叫Stig S. Bakken的人提出了一个想法,其目的是为PHP社区提供可以重复使用的库,并叫它为Pear。我想很多人听过或用过这货。

Composer和Pear的目的差不多。

一个疑问就是Pear比Composer诞生早了10年,但是为何它英雄败北了那?

总结几点不同吧

  • Pear必须全局安装,而Composer可以全局和局部安装,Composer具有更好的安装渠道。
  • Pear所有提交的代码必须经过Pear-review,这也注定了Pear上扩展包的版本更替会慢的很,而Composer没有这个限制,你能跟上开发者的版本更替。
  • 结构限制,Pear相对严格,而Composer灵活的多,你可以在项目的任何时期引入composer扩展包,任何一个文件夹(默认为vendor)。
  • PHP高级属性的不断出现也是推动Composer更快前进的一个原因。

上面原因不是全部,而且谨慎、守规矩、渠道限制也未必是坏事,但是它的确影响了Pear的发展,而Composer更加具有冒险精神、更加包容和灵活。

对于e文好的可以看下这篇文章,The rise of Composer and the fall of PEAR,让Pear安静的死去吧。

Composer来了

2012年,就是Pear发布12年后的一天,Nils Adermann及Jordi Boggiano提出Composer工具并发布第一个版本。

这一天是2012年3月1日,当然在中国这个日期也很重要 – 【小学生开学】。

omposer的使命就是帮你为项目自动安装所依赖的开发包,很多理念都借鉴自 npm 和 Bundler, 包含了一个依赖解析器,用来处理开发包之间复杂的依赖关系;另外,它还包含了下载器、安装器等有趣的东西。

这个就是Composer创始人之一 Nils Adermann的推特,竟然美国前总统奥巴马也关注了它,赶紧看看你的微博啥的。

Composer就这样一路前行,有几个网站你要知道

Composer 就这样来了。

 

号外,在2018年的今天,创始人又发布了一份具有68页的PDF文档,通过它你能更好的理解composer。

送你一份Composer创始人2018年发布的最佳实践文档

一份长达68页的PDF文档,Composer创始人告诉你如何正确使用composer工具以及未来发展规划,PHP们必看。

进入公众号后输入 cpdf 获取来自 Nai8.me 的服务

安装Composer

Composer的运行是有要求的,你的机器上必须有PHP环境并且版本不能低于PHP5.3.2,考虑到多数伙伴都是Win上开发,我们就以这个为例。

【安装程序安装】

这个很方便,不过我没太用过,Composer提供了一个安装程序( getcomposer.org/Composer-Se… ),好处是它将安装最新版本的 Composer ,并设置好系统的环境变量,因此你可以在任何目录下直接使用 composer 命令。

【手动安装】

按照官方文档来是最靠谱的

C:\Users\username>cd C:\bin
C:\bin>php -r "readfile('https://getcomposer.org/installer');" | php

我们来说明下官方给的代码,这是一个PHP命令行模式。

  • -r 表示可以在命令行内运行单行 PHP 代码,不需要PHP的开始和结束符
  • readfile好理解,该函数读入一个文件并写入到输出缓冲。
  • | php 用php执行刚刚readfile读到缓冲区的文件。

就是说你可以先在浏览器 getcomposer.org/installer 下载下来installer,然后执行下面代码,结果是一样的

php installer

让我们开始下载

要注意,上面命令需要你的php打开php_openssl支持。

上面是一种方法,还有你可以通过curl获取远程的文件,如下代码

curl -sS https://getcomposer.org/installer | php

和上面的思路一样,下载installer后用php对其执行进行继续的工作。

现在通过上面的行为,我将composer.phar下载到我的项目中(局部)。

composer.phar

使用 composer.phar 我们就可以进行composer包的安装和管理了,composer.phar其实是一个pear包,什么意思?它是一个php的包,看下结构。

我们可以通过它做事情了,比如 -V获得composer当前版本。

php composer.phar -V

不止这些命令,我们看看(输入小v,-v)

php composer.phar -v

你会看到很多很多命令,太多我就不截图了,后面我们会都说明到,比如

  • about
  • archive
  • config
  • global
  • home
  • install
  • update
  • require
  • search
  • self-update
  • show
  • …….

这些命令让我们和composer服务器建立了联系。

全局安装

很高兴现在我们可以使用它了,但是似乎每次输入 php composer.phar 老麻烦,接下来我们简化下工作。

  • 首先找到你的php安装目录(就是php.exe所在的目录,我们假设为D:\PHP)
  • 把刚下载的composer.phar弄到上面目录D:\PHP里
  • 在D:\PHP新建一个名为composer.bat的文件,内容为 @php “%~dp0composer.phar” %*
  • 添加php环境变量。右键我的电脑-属性-高级系统设置-环境变量。找到“系统变量”中名为Path,双击编辑,在最后加入分号和php目录位置,如;D:\PHP

最后一条是让命令行直接写php可以生效,这样上面的composer.bat才可以。如果是linux和mac会简单的多。

通过这些我想你知道了composer是什么,那么对于composer发布的各扩展库,这个工具是如何加载它们那?接下来我们研究下。

你不知道的Composer加载方式

我们以Yii2为例,当我们通过Composer生成了一个Yii2程序后,会在vendor下建立一个autoload.php文件,它负责帮我们自动加载vendor内的各种库(yii2核心库也在vendor内,你懂得!)。

而你一定知道Yii2的入口文件index.php有一行。

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

由此可见,Yii2对Composer的友好程度,也难怪~孤木不成林,Yii2也要靠无数个Composer扩展枝干才能变成参天大树。

下面开始正式讲解Composer的autoload,告诉你各式各样扩展安装后,我们并没有使用include / require,那么Composer是如何帮我们找到他们的那?

目前为止,Composer一共支持4种自动加载方式

  1. PSR-0
  2. PSR-4
  3. class-map
  4. 直接包含file

这四种方式足以让Composer涵盖地球上所有的PHP第三方扩展库。

PSR是一套PHP开发标准,现在大多数主流框架都在支持,工兵连已经开专题分享PSR干货。

PSR-4

PSR-4是Composer推荐使用的一种方式,因为它更易使用并能带来更简洁的目录结构。在一个扩展的composer.json里是这样进行配置的:

{
    "autoload": {
        "psr-4": {
            "Foo\\": "src/",
        }
    }
}

key和value就定义出了namespace以及其对应的目录映射。按照PSR-4的规则,当试图自动加载”Foo\Bar\Baz”类的使用,会去寻找”src\Bar\Baz.php”这个文件,如果它存在则加载,要注意的是此时”Foo\”并不会出现在文件路径中。

而composer.json这样的配置会被Composer转换成namespace与文件目录的MAP形式,并存在vendor/composer/autoload_psr4.php文件中,所以如果你安装的某个扩展自动加载是PSR-4形式,你可以在autoload_psr4.php找到它的真实路径。

PSR-0

这是一个已经过时的标准,那是在遥远的PHP5.2时代,你我都知道,PHP5.3之后才有了类似namespace这样的高级属性,所以PSR-0更多是考虑<=5.2时代的扩展,于是乎PSR组织用了一个伪namespace的做法。

有点蒙圈么?那我们来看代码你就明白了。

{
    "autoload": {
        "psr-0": {
            "Foo\\": "src/",
        }
    }
}

我们来分析这个扩展的加载方式,什么是伪namespace那?当我们用这个库的时候

$model = new Foo_Bar_Baz();

对的,PSR-0的时代,有很多以下划线分隔的类名,它代表。。。它代表。。。

src/Foo/Bar/Baz.php

聪明的你一定明白什么是伪namespace了吧,通过命名的下划线来映射目录结构。 哎,那个时代的标准制定者们也真心不容易呀。

Class-map方式

{
    "autoload": {
        "classmap": ["src/", "lib/"]
    }
}

这个加载方式比较容易理解,当Composer开始安装扩展的时候,会根据composer.json里的这个 autoload 告诉的方式classmap,来遍历src、lib目录然后将里面的类文件和其路径一一对应,存放到vendor/composer/autoload_classmap.php内。

例如src/下有一个BaseController类,那么在autoload_classmap.php文件中,就会生成这样的配置:

'BaseController' => $baseDir . '/src/BaseController.php'

若你还不懂,去看看autoload_classmap.php吧。

File方式

有了上面这些加载方式还不够么? 是的,还会有一些供全局使用的比如帮助等这样函数,那么好吧,我们就讲这些文件直接包含进来好了。

{
    "autoload": {
        "files": ["src/MyLibrary/functions.php"]
    }
}

Composer安装扩展后会将其放到

vendor/composer/autoload_files.php

到此刻,世界清静了,Composer可以加载我大PHP世界的各种库,只要你想,就可以自动加载。

现在我们知道了composer是个啥,并且知道扩展的加载方式,下面我们说说composer.json,composer到底要如何记载扩展库都是由此json文件决定,它就像一份菜单,告诉你这个菜是啥、怎么做、发明者是谁等等等等。

一份菜单 – 解读composer.json的各项内容

name *

包名,它包括供应商名称和项目名称,使用 / 分开,比如下面的样子。

abei2017/yii2-emoji

这个主要起到一个命名空间的作用,比如一个项目可以需要 abei2017/yii2-emoji 和 abei2017/yii2-cool-sms ,那么在vendor里可以将yii2-emoji和yii2-cool-sms都放到abei2017文件夹下。

另外这样做可以避免重复,比如开发者abei2017和开发者anan2017多做了库yii2-ext这个扩展,因为有命名空间的限制,所以不不会冲突。

description *

一个包的简短描述。通常这个最长只有一行。比如看下面yii2的一个description。

{
    "name": "yiisoft/yii2-app-basic",
    "description": "Yii 2 Basic Project Template"
}

version

版本,不是必须的,并且建议忽略。所以这里也不在进行说明,毕竟我们都是放到github上,给composer提交的时候它会自己分析。

type *

包的安装类型,默认为 library。你可以设定一个自定义的类型。这可以是一个 wordpress-plugin等。这些类型都将是具体到某一个项目,而对应的项目将要提供一种能够安装该类型包的安装程序。

比如我们开发的yii2扩展,它的类型就是 yii2-extension,而yii2程序提供了一个逻辑进行该包的处理。

vendor/yiisoft/yii2-composer/Installer.php

当然composer原生支持以下4种类型:

  • library: 这是默认类型,它会简单的将文件复制到 vendor 目录。
  • project: 这表示当前包是一个项目,而不是一个库。
  • metapackage: 当一个空的包,包含依赖并且需要触发依赖的安装,这将不会对系统写入额外的文件。因此这种安装类型并不需要一个 dist 或 source。
  • composer-plugin: 一个安装类型为 composer-plugin 的包,它有一个自定义安装类型,可以为其它包提供一个 installler。

仅在你需要一个自定义的安装逻辑时才使用它。建议忽略这个属性,采用默认的 library。

keywords

该包相关的关键词的数组。这些可用于搜索和过滤。

homepage

该项目网站的 URL 地址。

time

版本发布时间。必须符合 YYYY-MM-DD 或 YYYY-MM-DD HH:MM:SS 格式。

license

协议,这个还是写上吧,最近因为版权除了很多事,比如某某大公司把开发者的代码申请了专利云云。

  • Apache-2.0
  • BSD-2-Clause
  • BSD-3-Clause
  • BSD-4-Clause
  • GPL-2.0
  • GPL-2.0+
  • GPL-3.0
  • GPL-3.0+
  • LGPL-2.1
  • LGPL-2.1+
  • LGPL-3.0
  • LGPL-3.0+
  • MIT

对于闭源软件,你必须使用 “proprietary” 协议标识符。

license的一些写法如下

"license": "MIT" // abei2017/yii2-emoji
"license": "BSD-3-Clause",// yii2
"license": ["LGPL-2.1","GPL-3.0+"]
"license": "(LGPL-2.1 or GPL-3.0+)"
"license": "(CC-BY-4.0 and MIT)",   // emojione/emojione

使用一个扩展时候一定先看看它的协议

authors

选填,建议填写,是一个数组形式,如下图

"authors": [
    {
        "name": "Qiang Xue",
        "email": "qiang.xue@gmail.com",
        "homepage": "http://www.yiiframework.com/",
        "role": "Founder and project lead"
    },
    {
        "name": "Alexander Makarov",
        "email": "sam@rmcreative.ru",
        "homepage": "http://rmcreative.ru/",
        "role": "Core framework development"
    }
],

这个对象包含以下属性:

  1. name: 作者的姓名,通常使用真名。
  2. email: 作者的 email 地址。
  3. homepage: 作者主页的 URL 地址。
  4. role: 该作者在此项目中担任的角色(例:开发人员 或 翻译)。

support

一些支持,比如有个论坛、有个聊天时等等,看下面代码

"support": {
    "issues": "https://github.com/yiisoft/yii2/issues?state=open",
    "forum": "http://www.yiiframework.com/forum/",
    "wiki": "http://www.yiiframework.com/wiki/",
    "irc": "irc://irc.freenode.net/yii",
    "source": "https://github.com/yiisoft/yii2"
}

这个对象包含以下属性:

  1. email: 项目支持 email 地址。
  2. issues: 跟踪问题的 URL 地址。
  3. forum: 论坛地址。
  4. wiki: Wiki 地址。
  5. irc: IRC 聊天频道地址,类似于 irc://server/channel。
  6. source: 网址浏览或下载源。

require*

必须的软件包列表,除非这些依赖被满足,否则不会完成安装。这个是很重要的,比如你按照yii2-emoji,它的require是下面的样子。

"require": {
    "yiisoft/yii2": "*",
    "emojione/emojione": "^3.1"
}

则必须还要安装yiisoft/yii2和emojione/emojione,如果系统中以及存在则不用再安装。

require-dev (root-only)

这个列表是为开发或测试等目的,额外列出的依赖。可以使用 –no-dev 参数来跳过 require-dev 字段中列出的包。

autoload

PHP autoloader 的自动加载映射。存在vendor/composer里的一些文件的一些映射关系。

PSR4(vendor/composer/autoload_psr4.php),看如下代码

"autoload": {
    "psr-4": {
        "abei2017\\emoji\\": "src"
    }
}

那么这个设置代表了什么那?

use abei2017\emoji\Emoji
// 程序回去src文件夹找Emoji.php文件

PSR0(vendor/composer/autoload_namespaces.php)

一个重要的区别:PSR0里面最后一个\之后的类名中,如果有下划线,则会转换成路径分隔符,如Name_Space_Test会转换成Name\Space\Test.php。在PSR4中下划线不存在实际意义

Classmap(vendor/composer/autoload_classmap.php)这个 map 是经过扫描指定目录(同样支持直接精确到文件)。

你可以用 classmap 生成支持支持自定义加载的不遵循 PSR-0/4 规范的类库。要配置它指向需要的目录,以便能够准确搜索到类文件。

//phpunit
"autoload": {
    "classmap": [
        "src/"
    ]
},

Files

如果你想要明确的指定,在每次请求时都要载入某些文件,那么你可以使用 ‘files’ autoloading。通常作为函数库的载入方式(而非类库)。

{
    "autoload": {
        "files": ["src/MyLibrary/functions.php"]
    }
}

include-path

不建议:这是目前唯一支持传统项目的做法,所有新的代码都建议使用自动加载。 这是一个过时的做法,但 Composer 将仍然保留这个功能。

{
    "include-path": ["lib/"]
}

minimum-stability

这定义了通过稳定性过滤包的默认行为。默认为 stable(稳定)。因此如果你依赖于一个 dev(开发)包,你应该明确的进行定义。

可用的稳定性标识(按字母排序):dev、alpha、beta、RC、stable。

repositories

使用自定义的包资源库。

默认情况下 composer 只使用 packagist 作为包的资源库。通过指定资源库,你可以从其他地方获取资源包。

Repositories 并不是递归调用的,只能在“Root包”的 composer.json 中定义。附属包中的 composer.json 将被忽略。

archive

这些选项在创建包存档时使用。

exclude: 允许设置一个需要被排除的路径的列表。使用与 .gitignore 文件相同的语法。一个前导的(!)将会使其变成白名单而无视之前相同目录的排除设定。前导斜杠只会在项目的相对路径的开头匹配。星号为通配符。

{
    "archive": {
        "exclude": ["/foo/bar", "baz", "/*.test", "!/foo/bar/baz"]
    }
}

通过composer + json就可以进行安装,当然composer还有强大的命令行参数,接下来为你一一说明。

Composer命令行

启动:命令行输入composer 或 composer -v既能看到命令列表,一共35个。

介绍其中的 about、init、install、update、clear-cache/clearcache、archive、browse\home 等重点命令。

about

这个命令实际意义不大,相当于composer的一句话简介吧,也不需要其他参数

init

顾名思义,初始化你的composer项目,再简单一点说就是向导的形式帮你生成一个composer.json,如果你喜欢手动创建composer.json也没有问题。

这个过程将你的项目也纳入了composer体系,composer.json里包含项目的基本信息(比如作者,项目名称等)和项目所需要的依赖(你vendor里的那些库),总之,通过init你新建了一个composer.json。

我们看一下它的样子

你暂时无需在意composer.json里那些key-value,我们将在composer.json篇详细讲解。

install & update

重要且非常常用的命令,这两个命令需要放一起说才更好理解,install – 安装、update – 更新。说到这里,我们有必要顺一顺composer安装一个扩展的逻辑,认真看,这将是本篇最最重要的部分。

我们要先科普下两个文件,composer.json和composer.lock

  • composer.json记录项目及依赖信息
  • composer.lock记录项目及依赖当前版本信息

比如在composer.json有一条依赖是 “abei2017/yii2-emoji”: “^1.0″,那么你在composer.lock可以看到yii2-emoji当前用的是1.0.0版本,所以才有了下面的逻辑。

当我们composer install后,composer安装器进行了如下操作

  1. 如果当前目录下存在 composer.lock 文件,它会从此文件读取依赖版本,进行处理。
  2. 如果你当前项目没有 composer.lock 文件,它会从composer.json来读取依赖版本并更新到依赖最新版本,最后生成composer.lock

composer.lock 是一个标尺。

当然如果你手动修改了composer.json,然后执行composer install后,会发现一个警告信息,看下图。

上面图中警告出现的场景是我在composer.json中改了项目的name值,然后composer install。这个警告是告诉我们Composer发现composer.json哈希值和composer.lock中记载的不同,因此不进行任何处理。

但是,但是,但是,我们如何在这个场景下保证json和lock文件一致那,其实也很简单,在我们改动了composer.json后执行如下命令

composer update nothing // 或composer update --lock

上面的命令不会处理依赖(有例外,如果改动了require数据,则会处理依赖),仅仅保证json和lock文件的一致。

要记住,install命令处理依赖的依据是composer.lock文件,比如一个image扩展当前最新版本是3.0,lock文件记录使用的是2.0,则install会按照2.0来安装,就像官方所说“composer.lock确保了一个项目组该库的每个使用者都能得到相同的依赖版本。”

接下来我们说说update,强大的update,永远追求最新版本的update。

update命令负责更新,从上面我们知道它能通过更新保证json和lock文件的一致,另外比如你在composer.json中修改了比如require(依赖)的增加或减少,执行 composer update也能直接帮你安装或删除相关依赖并保证json和lock文件的一致。

要记住的是 composer update 更新的是所有且更新到最新版本,如果要单独更新某个库,可以使用 composer update abei2017/yii2-emoji 。

update是一把利剑,它让很多人后悔莫已。

到此刻你会发现,install和update似乎都可以安装扩展,那么我们如何准确使用他们那?我们现在温习一下上面学习的结果,3条。

  • composer install 如有 composer.lock 文件,直接安装,否则从 composer.json 安装最新扩展包和依赖;
  • composer update 从 composer.json 安装最新扩展包和依赖;
  • composer update new/package – 添加安装 new/package, 可以指定版本,如: composer update new/package ~3.5.

所以一般我们如下部署程序

  1. 创建 composer.json,并添加依赖到的扩展包;
  2. 运行 composer install,安装扩展包并生成 composer.lock;
  3. 提交 composer.lock 到代码版本中;
  4. 克隆项目到生产环境,根目录下直接运行 composer install 从 composer.lock 中安装指定版本的扩展包以及其依赖;

一句话就是保证composer.lock的一致和稳定。其实最稳定安装扩展的方法是requrie命令(下篇讲到)。

另外上面是在思路方面为大家介绍install 和 update,这两个命令还有很多参数,刚阿北看了下到很好了解,这里列出来不一一讲解,有不懂留言即可。

install

  • –prefer-source: 下载包的方式有两种: source 和 dist。对于稳定版本 composer 将默认使用 dist 方式。而 source 表示版本控制源 。如果 –prefer-source 是被启用的,composer 将从 source 安装(如果有的话)。如果想要使用一个 bugfix 到你的项目,这是非常有用的。并且可以直接从本地的版本库直接获取依赖关系。
  • –prefer-dist: 与 –prefer-source 相反,composer 将尽可能的从 dist 获取,这将大幅度的加快在 build servers 上的安装。这也是一个回避 git 问题的途径,如果你不清楚如何正确的设置。
  • –dry-run: 如果你只是想演示而并非实际安装一个包,你可以运行 –dry-run 命令,它将模拟安装并显示将会发生什么。
  • –dev: 安装 require-dev 字段中列出的包(这是一个默认值)。
  • –no-dev: 跳过 require-dev 字段中列出的包。
  • –no-scripts: 跳过 composer.json 文件中定义的脚本。
  • –no-plugins: 关闭 plugins。
  • –no-progress: 移除进度信息,这可以避免一些不处理换行的终端或脚本出现混乱的显示。
  • –optimize-autoloader (-o): 转换 PSR-0/4 autoloading 到 classmap 可以获得更快的加载支持。特别是在生产环境下建议这么做,但由于运行需要一些时间,因此并没有作为默认值。

update

  • –prefer-source: 当有可用的包时,从 source 安装。
  • –prefer-dist: 当有可用的包时,从 dist 安装。
  • –dry-run: 模拟命令,并没有做实际的操作。
  • –dev: 安装 require-dev 字段中列出的包(这是一个默认值)。
  • –no-dev: 跳过 require-dev 字段中列出的包。
  • –no-scripts: 跳过 composer.json 文件中定义的脚本。
  • –no-plugins: 关闭 plugins。
  • –no-progress: 移除进度信息,这可以避免一些不处理换行的终端或脚本出现混乱的显示。
  • –optimize-autoloader (-o): 转换 PSR-0/4 autoloading 到 classmap 可以获得更快的加载支持。特别是在生产环境下建议这么做,但由于运行需要一些时间,因此并没有作为默认值。
  • –lock: 仅更新 lock 文件的 hash,取消有关 lock 文件过时的警告。
  • –with-dependencies 同时更新白名单内包的依赖关系,这将进行递归更新。

clear-cache & clearcache

这个要说下,和名字一样,清空所有缓存,我们来顺一顺。

当我们使用require安装一个扩展的时候,composer会在我们机器上留一个缓存文件夹,一般是在 C:\Users\Administrator\AppData\Local\Composer(需要执行一次require才有会Composer目录),它的基本结构如下

切记,不要和全局目录混淆了,全局目录的位置为C:\Users\Administrator\AppData\Roaming\Composer,里面含有比如全局配置文件,全局安装的扩展包等。

下面我们来看一下这个过程,首先我requrie了一个扩展包,如下图

如图所示,这个过程是从服务器下载的,然后我们看看缓存文件夹

看到了吧,此刻在缓存文件夹的files子文件夹里多了一个abei2017/yii2-emoji/xxx.zip的文件,这个就是缓存,接下来我们删除项目的yii2-emoji然后再安装,看看有何不同了,看下图

不一样了吧,下一次从缓存读取,你是否发现速度快了很多,那是必须的。

所以,有些问题你可以清空缓存试试,比如版本问题等等。好了,我们还没有说clear-cache命令那(clearcache一个意思)

composer clearcache

流程明白了吧,记住,这个clearcache也同时删除了C:\Users\Administrator\AppData\Local\下的Composer文件夹自身。

archive

首先要知道这仍然是一个从远程下载的过程,只不过下载后将其打包成了zip/tar压缩包,比如你可以打包某个扩展发给你的同事等。官方手册的书写方法会让一些初学者误会 对于包的指定是不能含有vendor的,接下来的命令是正确的

composer archive abei2017/yii2-emoji --format=zip --dir ./zip

结果如下图,我们一一说明下。

  1. 如果要指定版本,后面空格然后直接放版本号就可以,不指定也没事,会自动选择稳定最新的。
  2. 两种格式,不写则默认是tar,推荐使用zip。
  3. 如果不指定就在当前项目的根目录,你可以指定当前项目的相对路径,比如 ./zip,composer如果发现无此目录会自己建立,当然你也可以指定比如 D:\zip,一个绝对的路径。
  4. 从4中你应该看到,这仍然是一个install的过程,不过你不用担心,虽然是install,但是它并没有对你的vendor进行写入,仅仅是生成了归档文件而已。

要注意:运行此命令生成归档文件并不会下载此扩展相关的依赖。

browse && home

浏览,这个命令我觉得最大的一个用处就是打开仓库页面、比如我输入了

composer browse abei2017/yii2-emoji

命令行会调出浏览器并打开 github.com/abei2017/yi… ,这个命令和另外一个home命令差不多。

composer home abei2017/yii2-emoji

config

顾名思义,使用此命令可以编辑 Composer 的一些基本设置,无论是本地的 composer.json 或者全局的 config.json 文件。

我们可以使用 composer config –list 来看看当下可以配置的所有项(composer默认项 + 当前项目项,当前项目优先)。

当然我们可以使用 composer config –list –global 列出项目的全局配置(composer默认项 + 全局配置项,全局优先)。

通过config我们首先可以查看当前项目的配置信息,比如bin文件夹,cache等等,这里列出几个。

[repositories.packagist.org.type] composer
[repositories.packagist.org.url] https://packagist.phpcomposer.com
[process-timeout] 300
[use-include-path] false
[preferred-install] auto
[notify-on-install] true
[github-protocols] [https, ssh]
[vendor-dir] vendor (F:\wwwroot\BeiGeXiongDiLian/vendor)
[bin-dir] {$vendor-dir}/bin (F:\wwwroot\BeiGeXiongDiLian/vendor/bin)
[cache-dir] C:/Users/Administrator/AppData/Local/Composer
[data-dir] C:/Users/Administrator/AppData/Roaming/Composer
[cache-files-dir] {$cache-dir}/files (C:/Users/Administrator/AppData/Local/Composer/files)
[cache-repo-dir] {$cache-dir}/repo (C:/Users/Administrator/AppData/Local/Composer/repo)
[cache-vcs-dir] {$cache-dir}/vcs (C:/Users/Administrator/AppData/Local/Composer/vcs)
[cache-ttl] 15552000
[cache-files-ttl] 15552000
[cache-files-maxsize] 300MiB (314572800)
[bin-compat] auto
.......

当然除了查看,我们也能修改某个配置项,比如下面的代码

composer config process-timeout 1900
composer config -g process-timeout 1700
  • 第一行修改了当前项目的配置,信息在项目root目录的composer.json存储。
  • 第二行修改了全局的配置,信息在[data-dir]目录的config.json中存储。

当然如果配置项是数组形式,你可以多写几个value,空格分开。

当然config还有一些参数,比如–editor (用编辑器打开修改),–unset (移除某个配置项)等。

create-project

主要用来安装一个项目,比如我们在安装yii2的时候就有如下的语句

composer create-project --prefer-dist yiisoft/yii2-app-basic basic

这相当于执行了一个 git clone 或 svn checkout 命令后将这个包的依赖安装到它自己的 vendor 目录。

这个命令也有挺多的参数

  • –stability (-s): 资源包的最低稳定版本,默认为 stable。
  • –prefer-source: 当有可用的包时,从 source 安装。
  • –prefer-dist: 当有可用的包时,从 dist 安装。
  • –dev: 安装 require-dev 字段中列出的包。
  • –no-install: 禁止安装包的依赖。

depends

依赖性检测,命令可以查出已安装在你项目中的某个包,是否正在被其它的包所依赖,并列出他们。

假设我们为程序安装了abei2017/yii2-emoji,而yii2-emoji依赖于emojione/emojione,看看执行depends命令的结果。

composer depends emojione/emojione
abei2017/yii2-emoji  1.0.0  requires  emojione/emojione (^3.1)

composer depends abei2017/yii2-emoji
yiisoft/yii2-app-basic  -  requires  abei2017/yii2-emoji (^1.0)

看明白了吧?默认是根据json文件的require配置项检测,也可以根绝require-dev来检查,传递一个参数即可,如下面代码。

composer depends --link-type=require-dev emojione/emojione

diagnose

错误诊断,要注意的是这个命令只是检查composer.json及composer一些配置项是否正确,不检查依赖逻辑。看看下面代码,检查的流程。

Checking composer.json: OK
Checking platform settings: OK
Checking git settings: OK
Checking http connectivity to packagist: OK
Checking https connectivity to packagist: OK
Checking github.com oauth access: OK
Checking disk free space: OK
Checking pubkeys:
Tags Public Key Fingerprint: 57815BA2 7E54DC31 7ECC7CC5 573090D0  87719BA6 8F3BB723 4E5D42D0 84A14642
Dev Public Key Fingerprint: 4AC45767 E5EC2265 2F0C1167 CBBB8A2B  0C708369 153E328C AD90147D AFE50952
OK
Checking composer version: OK

dump-autoload / dumpautoload

某些情况下你需要更新 autoloader,例如在你的包中加入了一个新的类。你可以使用 dump-autoload 来完成,而不必执行 install 或 update 命令。

它有两个参数:–optimize (-o) & –no-dev,其中–optimize (-o)是个性能优化选项,在生产环境如下命令可以提高加载性能。

composer dumpautoload --optimize

不加–optimize这一选项,你可能会发现20%到25%的性能损失。

global

允许你在 COMPOSER_HOME 目录下执行其它命令,像 install、require 或 update。看下面代码

composer global require abei2017/yii2-emoji

将 abei2017/yii2-emoji 全局安装并使用。

info

这个参数比较简单,如果你用 composer info 则会直接列出当前项目的所有依赖(名称+版本+简介),如果你使用 composer info abei2017/yii2-emoji跟了一个扩展,则将扩展的composer.json内容整理下显示出来。

licenses

将当前项目所有依赖的协议都列出来,方便你查询,如下面的代码

//composer licenses
abei2017/yii2-emoji                 1.0.0    MIT
behat/gherkin                       v4.4.5   MIT
bower-asset/bootstrap               v3.3.7   MIT
bower-asset/jquery                  2.2.4    MIT
bower-asset/jquery.inputmask        3.3.6    http://opensource.org/licenses/mit-license.php
bower-asset/punycode                v1.3.2   none
bower-asset/typeahead.js            v0.11.1  none
bower-asset/yii2-pjax               v2.0.6   MIT
cebe/markdown                       1.1.2    MIT
.......

list

好简单,列出所有命令。

show

列出所有可用的扩展,我们也可以使用比如 composer show abei2017/yii2-emoji 查看一个扩展的详情,还可以帅选 composer show abei2017/*

这个命令有一些参数

  • –all 这是一个很大的命令,列出在packagist.org上所有可用的扩展(名字 + 版本 + 简介)
  • –installed (-i) 列出我们项目安装的扩展
  • –platform (-p) 只列出平台扩展(php & extensions)。
  • –available (-a) 列出当前可以获得的扩展。
  • –self (-s) 列出 root扩展信息,即当前项目的。
  • –name-only (-N) 只显示名字(不显示版本和简介)
  • –path (-P) 显示当前项目安装的扩展的物理目录。
  • –tree 这个命令也不错,列出所有的依赖及其依赖关系
  • –outdated (-o) 列出所有有新版的扩展

outdated

这个命令也不错,等于composer show -lo

remove

删除一个扩展,该命令首先改动composer.json,删除相应的依赖,然后执行。如果要一次删除多个扩展,可以一次写出,空格分开即可。

这个命令也有很多参数,比如删除库后不进行依赖的更新等。

  • –dev: 从 require-dev 删除扩展。
  • –no-update: 禁用依赖关系的自动更新。
  • –no-progress: 移除进度信息,这可以避免一些不处理换行的终端或脚本出现混乱的显示。
  • –update-with-dependencies: 同时更新删除扩展的依赖扩展。

require

添加一个扩展并且更新到composer.json内

composer require abei2017/yii2-emoji

改命令参数也很多

  • –prefer-source: 当有可用的包时,从 source 安装。
  • –prefer-dist: 当有可用的包时,从 dist 安装。
  • –dev: 安装 require-dev 字段中列出的包。
  • –no-update: 禁用依赖关系的自动更新。
  • –no-progress: 移除进度信息,这可以避免一些不处理换行的终端或脚本出现混乱的显示。
  • –update-with-dependencies 一并更新新装包的依赖。

到现在为止我想你已经可以正常使用composer了,最后再说说如何发布一个扩展。

轻松发布一个自己的composer扩展

从composer.json开始

是的,既然我们在使用一个composer扩展的时候根据一份composer.json来安装依赖包,那么我们发布扩展包的时候,也应该先有一份描述自己的清单 – composer.json。

你可能会问,我现在开发的系统使用了composer来安装依赖,我自己项目根目录下也有一个composer.json,那我的项目是一个扩展包么?

是的,你的项目也是一个包,但是此刻它不能发布、不能被别人通过composer安装,因为它少了一个最重要的元素 —- 名字

就是我们之前讲的composer.json中的name,具体name的约定我想你已经通过之前的学习了解了吧,不懂可以看看速查表传送门

如果你不知道拿什么作为供应商的名称, 那么使用你 github 上的用户名通常是不错的选择。 虽然包名不区分大小写,但惯例是使用小写字母,并用连字符作为单词的分隔。

比如下面的写法都是不错的

  • abei2017/emoji
  • abei2017/yii2-emoji
  • china-go/emoji
  • china-go/yii2-emoji

当然,composer也为我们提供了 init 命令,一问一答式的帮我们建立composer.json,这样更简单。

代码结构和自动加载方式

先说结构吧,一个包是应该有测试文档、有源代码、有说明文档,甚至还要有一些例子,所以将一堆文件放到一个文件夹并不是好的结构,我一般喜欢如下的写法,不过这不局限,思路可以理清楚就是好的结构。

我的结构如下

-src/
--src/Emoji.php
--src/Event.php
--src/....
-test/
--test/a.php
--test/b.php
--test/...
-example/
--example/example01.php
--example/example02.php
--example/...
-README.md
-composer.json

而关于自动加载方式,如果是一个新的扩展,我喜欢也推荐用psr-4规范。 那就需要在composer.json有如下定义

"autoload": {
    "psr-4": {
        "abei2017\\emoji\\": "src"
    }
}

具体psr-4的规范可以去官网看一下,composer安装了你的扩展后,映射关系会出现在 vendor\composer\autoload_psr4.php 文件内容中。

我在此处把abei2017/yii2-emoji的composer.json说明下,帮助大家理解。

{
    "name": "abei2017/yii2-emoji",
    "description": "一个yii2的emoji扩展",
    "type": "yii2-extension",
    "keywords": ["yii2","extension"],
    "license": "MIT",
    "authors": [
        {
            "name": "abei",
            "email": "abei@nai8.me"
        }
    ],
    "require": {
        "yiisoft/yii2": "*",
        "emojione/emojione": "^3.1"
    },
    "autoload": {
        "psr-4": {
            "abei2017\\emoji\\": "src"
        }
    }
}

简要说明如下

  • 名字为abei2017/yii2-emoji,abei2017是我github的名字
  • 采用MIT协议发布
  • yii2-emoji能运行要依赖于 yiisoft/yii2 和 emojione/emojione 的正确部署,见require
  • 自动加载采用psr-4,命名空间和扩展的src下文件一一映射

提交到github

然后在github上建立一个空的仓库,记住仓库git地址。回到我们机器上的扩展目录,执行git操作。

>git init
>git remote set-url origin --push --add git@github.com:abei2017/xxx.git
> git add .
> git commit
> git push origin master

当然你如果使用phpstorm,这一切会更简单。传送门

总之,你现在将本地文件git到了远程的仓库。

coding…coding…coding

经过无数个夜晚,你完成了扩展的功能。

然后我们在github上为它建立了一个版本,叫做1.0

提交给Packagist

大家都知道,Packagist(packagist.org/)是composer的…

注册账号

首先我们要在Packagist上注册一个账号,过程十分简单,这年头谁还没注册过呀。

submit

然后点击右上角的submit(packagist.org/packages/su… ) 提交即可。Packagist能自动识别git/svn,你只需要提交github的仓库地址。

一会儿,Packagist就完成了自己的分析和采集,你就可以通过 composer require xxx 使用了。国内镜像用户要慢些,镜像要每隔一点时间采集一次Packagist上的包。

升级你的包

过了一段时间,你的包有了新版本,可能在github上新建了2.0版本,这儿时候回到你在 Packagist 上的此包页面,点击下update即可,当然你也可以通过GitHub Service Hook实现自动update

到这里,你就成功的发布了你的包,简单吧。