【译】现代化的PHP开发--Composer

名人之声

就算它工作不正常也别担心。如果一切正常,你早该失业了

——Mosher的软件工程定律

来源/https://www.startutorial.com/articles/view/modern-php-developer-composer

翻译/Lemon黄

现代化的PHP开发,一定要知道包管理,即Composer。

1 包管理

通常来说,一组代码块组成一个方法,一组方法组成一个类,一组类形成一个包(package)。

可重用的包可以放入任何一个项目中,并且无需再添加任何功能即可使用。

一个包能为客户端提供API来实现单一的目标。

包能够帮助我们的项目实现“DRY(Don't Repeat Yourself--不要重复)”,软件开发的一个原则,就是减少各种信息(代码)的重复。

在大多数情况下,包是有依赖关系的。例,当“包A”需要 “包B”才能运行时,可以说“包A”依赖于“包B”。一个包有一系列的依赖关系是很常见的(例,A依赖于B,B依赖于C)。

假设没有包管理器,我们需要做什么使得依赖于B包的A包能工作起来?当我们下载A包的源代码时,发现A依赖于B包,以致于我们又要去下载B包的源代码。找到B包的源代码后,可能A还是无法工作,因为我们还要确保下载了B包的正确版本。这种依赖的关系的故事还可以继续下去。我们只讨论一个依赖关系,如果包A有多个依赖关系或者有一系列依赖关系,真很快就会变成一个噩梦。

所以,我们需要一个包管理器,一个可以解决所有依赖关系的管理器。

2 Composer vs. PEAR

PEAR:

在Composer之前,有一个叫做 PEAR 的东西。如果你很早就开始接触PHP,那你可能知道PEAR,因为它自1999年就已经存在。

PEAR的产生也是为了能重复使用包,这和Composer是类似的。但由于以下几个原因,它并不被开发者们推崇:

  • 与Composer不同,PEAR是一个系统范畴的包管理器。当有很多个项目 ,它们共享相同的依赖项,但每一个依赖项都有不同的版本时,PEAR这种方法会造成很多混乱和挫折。
  • 为了能让你的代码被PEAR的存储库所接受,需要一定数量的UP投票。这种方式抑制减缓了PEAR存储卡的增长。归根结底,开发者是为了编写代码,而不是为了提升代码而关注UP投票。

Composer:

Composer是PHP中应用程序级别的包管理器。它的灵感来自Node.js中的Npm和Ruby中的Bundler,是目前社区公认的包管理器。

Composer的生态系统由两部分组成:composer(用于安装包的命令行程序) 和 packagist(默认包的存储库)。

应用程序级别的包管理器意味着它以项目为基础来管理依赖项。这就很容易来管理很多个的项目,并能保持计算机的干净,因为它只将包下载到对应的项目目录中。

与PEAR不同的是,不需要获得任何的UP投票。所以,每个人都喜欢提交他们的代码包到Packagist存储库中。只要有人喜欢你的Packagist中提交的包,你就可以开始了(创作,开发package)。

Packagist

如上所述,Packagist(packagist.org)是composer的默认包存储库。截止到2015年9月,Packagist已经提供了69568个包。下一次,我们需要一个PHP包,我们很可能能在Packagist上找到我们要的包,而不用重头开始构建一个。作为开发人员,建议你用包的力量,因为它将节省你无数的时间和精力。截止到2015年9月,包装商提供了69568个包裹。

3 安装Composer

以下安装,基于MAC用户。

安装Composer的方式有两种作用域:本地作用域(也叫本地安装)和全局作用域(也叫全局安装)。根据专业的经验,我们建议在您的系统上(也就是全局安装)安装composer。毕竟,我们的系统上会有很多个PHP项目,我们很可能会使用composer来管理每个PHP项目的依赖关系。全局安装为我们节省了很多麻烦。

全局安装:

在终端(Terminal )中运行以下命令来全局安装composer:

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

mv composer.phar /usr/local/bin/composer

如果遇到与权限相关的任何错误,请在sudo模式下运行上面的命令(将sudo附加到每个命令)

本地安装:

在项目的根目录打开终端(Terminal )运行以下命令来本地安装composer:

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

有关composer的更详细的安装指南,请访问:

https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx

验证是否安装成功:

要验证是否正确安装了composer,请从安装了composer的目录运行下面的命令(如果composer是全局安装的,则在任何位置运行)。

composer about

如果看到类似于下面的输出,则说明安装成功。

Composer - Package Management for PHP
See https://getcomposer.org/ for more information.

4 使用Composer

Composer现在可以使用了,我们通过一个简单的例子来演示它的用法:

想象我们已经完成了一个完美的项目,我们希望生成模拟数据,例如,显示我们的客户的姓名和地址。如果数据是随机的,而且有意义的话,这会很酷,所以演示会看起来很真实。一种解决方案是键入一些假名称和地址,将它们存储在一个数组中,然后使用array_rand从数组中随机选择条目。正如你可能已经意识到的,这个解决方案听起来很乏味,不切实际。如果我们需要数百个用户的数据,会发生什么?我们需要一个救世主。

在Packagist上刚好有我们想要的包,这个很棒的包叫做 Faker。

接下来,我们就可以使用composer来安装 Faker。

在项目的根目录中,运行以下命令:

composer require fzaninotto/faker

composer需要几秒钟(毕竟是国外人开发的,在国内通常需要好几分钟,这个可以通过更改composer镜像来完成,大家百度一下)才能下载所需的文件。在composer下载引擎的作用下,composer从github下载faker的zip文件。除了下载所需的包,composer还将创建一些内部文件,我们稍后将对其进行研究。

现在我们去看看我们的项目目录,我们应该能够发现一些新创建的文件夹和文件,如下所示:

  • composer.json
  • composer.lock
  • vender

composer.json:

这个文件用来描述项目的依赖项。这是一个简单的json文件,向我们展示项目中安装了哪些包。

无论何时在命令行中运行composer require 命令,composer.json和composer.lock文件都将自动更新以反映项目中包的更改。

相反,如果将包添加到composer.json文件,则要运行 composer install 命令来下载新的包。如果要将所有包的版本更新为其版本约束指定的最新版本,可以运行composer update。如果要将所有包的版本更新为其版本约束指定的最新版本,可以运行composer update。

这就是composer的三个基本命令:

composer require:

这个命令用于将单个包添加到项目依赖项中。只要我们需要一个新的包,我们就可以运行它。这个真的很方便,因为我们根本不需要接触 composer.json文件。

此命令的另外一个用法是更新现有包的版本。例如,我们使用 composer require fzaninotto/faker 就已经安装了Faker的最新版本,如果我们不指定它的版本约束,则下载的是包的最新版本。但是我们的应用与Faker 1.4.0的版本无法兼容,我们需要Faker 1.2.0的版本,这时候我们就可以使用命令:composer require fzaninotto/faker:1.2 0,来安装。它将会下载我们指定的版本并相应更新项目中composer的相关文件。

composer install:

这个命令运行,首先会查找项目中是否有composer.lock文件,如果文件存在,则安装按文件中定义的包的确切版本,然后忽略composer.json文件。如果不存在,该命令将检查composer.json文件中定义的包,并下载与提供的版本约束匹配的包的最新版本。你能看出区别吗?使用composer.lock时,会下载准确的版本,而使用composer.json时,composer将始终尝试检索与提供的版本约束匹配的包的最新版本。当版本约束被定义为一个确切的数字时,两个动作都有相同的结果。然而,这种情况很少发生。

当我们的一个新的项目中已经定义了依赖项列表,当我们在这个项目中运行这个命令,这个命令回去安装所有列出的依赖项的包。或者我们从github上去下载别人的项目,在项目中运行此命令,也会自动下载项目中所列的依赖项的包。

在某些部署策略中,我们在生产环境中运行此命令,以便在从存储库中提取应用程序的源代码后来安装该应用程序。

composer update:

这个命令与composer install 不同,此命令此读取composer.json文件。它将现有的包更新到与composer.json文件中定义的提供的版本约束相匹配的最新版本。

我们可以使用这个命令来更新现有包的版本,类似于composer require。不同的是composer require不需要我们手动触发composer.json文件,它感觉更直观。

这个命令只从composer.json读取的事实带来了一个常见的陷阱,尤其是在生产环境中使用这个命令。我们在生产环境中不应该使用这个命令,以下是为什么的原因:

如果您的应用程序在本地开发环境中与Faker 1.2.0配合得很好,则可以将代码推送到生产环境并运行composer update。

由于我们的认知有限,我们不知道Faker的最新版本已经更新到了1.4.0。所以,composer会在生产环境中下载1.4.0的版本,因为我们在composer.json中定义Faker的版本约束为“fzaninotto/faker: 1.*”。因此,生产环境包的版本和开发环境的包的版本不一致,这不是我们预期的结果。

我们建议将composer.lock与composer.json一起部署到生产环境中,并在生产环境中使用composer install安装依赖项。

composer.lock:

虽然composer.json文件允许我们使用版本约束定义所需的包,但composer.lock会跟踪项目中安装的包的确切版本。换句话说,它存储了我们项目的当前状态。这是很重要的一点。

composer install首先读取composer.lock,这使得它成为一个更安全的命令,以下是为什么的理由:

如果从项目中完全删除vender文件夹,则将删除composer下载的所有包。现在再次运行composer install,它将获得与以前相同的软件包版本。

这就引出了我们的下一点。如果我们使用的是像git这样的版本控制系统,我们应该提交composer.lock吗?

答案是“这取决于项目的需要”。大多数时候,我们希望确保每个人在任何时候都共享相同的源代码。所以我们应当提交composer.lock。这是很常见的,因为我们大多数人都和一个团队一起工作。很少有不提交composer.lock的情况发生在我们开发包(库)时,因为用户很少需要在我们的包中运行composer安装。

composer在使用命令方面给了我们很大的灵活性,但是我们需要有以下一些规则来防止出现不必要的麻烦:

  • composer install是我们的朋友——在生产部署使用它。

一个标准的composer工作流:

  • 在composer.json中定义了一些依赖项:运行composer安装
  • 需要一个单独的包,运行:composer require some/package
  • 需要多个包:在composer.json文件中定义它们并运行composer update
  • 想要测试一个新发布的包,运行:composer require some/package:new-version
  • 准备测试发布的所有最新版本的包,运行:composer update

5 自动加载--Autoloading

在PHP中,我们可以使用了很多的include/require语句。这些语句的问题是,它们使我们的代码变得凌乱。最糟糕的是,每当我们更新目录结构时,我们都会做很多查找和替换工作。

解决方案是自动加载。它允许您定义搜索类的路径,这样就不必使用include/require手动执行。但当然,我们应该记住,实际上,自动加载仍在使用include/require。

现在,让我们回到我们的项目。有一个地方我们还没有真正探索过,那就是composer创建的vender目录。默认情况下,composer会将所有包下载到此目录。

composer实际上还生成了一个 vendor/autoload.php 的文件,该文件可以自由地为我们自动填充,使我们很容易的使用vender中的代码。

在我们的例子中,我们希望使用faker,这样我们可以简单地包含下面的文件,faker将被自动加载。

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

现在,我们可以开始使用Faker:

$faker = Faker\Factory::create();
 
echo $faker->name;

6 社区的力量

你现在应该对composer有一个相当的了解。开始使用它来管理项目的依赖关系。我们保证它会使你和你的同事的生活更容易。下一次你的项目需要什么,开始在Packagist上寻找它们。拥抱社区的力量!

本文分享自微信公众号 - Lemon黄(lemonhunag)

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

原始发表时间:2019-10-05

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏日常杂谈

哪吒数据提取、数据分析

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

12420
来自专栏HACK学习

一次学校财务处网站的简单测试

渗透测试的能力只有在实战中才能获得更好的提高,所以这次简单的讲一讲最近对我们学校的财务处网站的简单测试。

13520
来自专栏.NET技术与企业级解决方案

C#开发BIMFACE系列10 服务端API之获取文件下载链接

通过BIMFACE控制台或者调用服务接口上传文件成功后,默认场景下需要下载该源文件,下载文件一般需要知道文件的下载链接即可。BIMACE平台提供了“获取文件下载...

8330
来自专栏分享/效率/工具/软件

springboot2.0配置多数据源出错HikariPool-1 - jdbcUrl is required with driverClassName.

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

12640
来自专栏g歌德a

Java微信公众平台开发(六)--微信开发中的token获取

引用:access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储...

10630
来自专栏明年我18

使用HttpWebRequest post数据时要注意UrlEncode

今天在用HttpWebRequest类向一个远程页面post数据时,遇到了一个怪问题,总是出现500的内部服务器错误,通过查看远程服务器的log,发现报的是“无...

10130
来自专栏TestQA

python3下常用编解码与加解密

Python3相对于Python2的一大改变就是,对默认字符类型进行了修改。Python2中定义字符串默认为二进制字符串,强制加前缀u的才是unicode字符串...

13340
来自专栏二狗的DBA之路

nginx+php-fpm独立节点的部署wordpress笔记

今天同学说他分开部署nginx+php-fpm出现了问题,总是报502,正好我也没试验过,于是自己也做了一遍,也遇到些问题,记下来以备以后用到。

10930
来自专栏菲宇

RESTful API基本介绍

原文链接:https://www.cnblogs.com/derek1184405959/p/8716892.html...

13230
来自专栏分享/效率/工具/软件

(centos)yum配置保存package包

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

7820

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励