[转]PHP开发者必须了解的工具—Composer

时间:2024-06-10 21:03:20

本文转自:https://blog.****.net/Zhihua_W/article/details/80345973

Composer是PHP 用来管理依赖(dependency)关系的工具。你可以在自己的项目中声明所依赖的外部工具库(libraries),Composer 会帮你安装这些依赖的库文件。对于PHP开发者来说掌握Composer是必须的。对于使用者来说Composer非常的简单,通过简单的一条命令将需要的代码包下载到vendor目录下,然后开发者就可以引入包并使用了。

Composer由来

PHP最早加载类的方法在我们初学PHP时最早会面对的问题之一就是require与include差别何在?require_once与include_once又是什么?当我们明白这些问题之后在项目开发中,如果项目未使用框架,则会出现很多这样的代码:

require 'x1_class.php';
require 'x2_class.php';
require 'x3_class.php';
这样写我们又有了新的问题,许多文档用到同样的几个class类文件,于是在不同的地方都要重新载入一次,当类别多了起来,会显得很乱;此时,我们又想了一个新的方法,写一个PHP文件,负责载入所有的类文件,然后再其他文档中都载入这个文件,结果又有问题了:当类文件很多的时候,随便一个Web Page都会载入一堆Code,占用大量内存,怎么办呢?

为解决这个问题,PHP 5开始提供__autoload这种俗称“magic method”的函式。当你要使用的类别PHP找不到时,它会将类别名称当成字串丢进这个函式,在PHP喷error投降之前,做最后的尝试:

// autoload.php
function __autoload($classname) {
if ($classname === 'xxx.php'){
$filename = "./". $classname .".php";
include_once($filename);
} else if ($classname === 'yyy.php'){
$filename = "./library1/". $classname .".php";
include_once($filename);
} else if ($classname === 'zzz.php'){
$filename = "./library2/". $classname .".php";
include_once($filename);
}
}
也因为PHP这种“投降前最后一次尝试”的行为,有时会让没注意到的人困惑“奇怪我的code怎么跑得动?我根本没有require啊”,所以被称为“magic method”。如此一来,问题看来似乎解决了?如果我们仔细分析还是会发现一个问题,就是这个__autoload函式内容会变得很巨大。以上面的例子来说,一下会去根目录找、一下会去library1资料夹、一下会去library2资料夹寻找。在整理加载文件的时候,显得有些混乱。
于是PHP从5.1.2开始,多提供了一个函式 “spl_autoload_register”。可以多写几个autoload函式,然后注册起来,效果跟直接使用__autoload相同。现在可以针对不同用途的类别,分批autoload了。

spl_autoload_register('library1_loader');
spl_autoload_register('library2_loader');
spl_autoload_register('basic_loader');

function library1_loader($classname) {
$filename = "./library1/". $classname .".php";
include_once($filename);
}

function library2_loader($classname) {
$filename = "./library/". $classname .".php";
include_once($filename);
}

function basic_loader($classname) {
$filename = "./". $classname .".php";
include_once($filename);
}
每个loader内容可以做很多变化。可以多写判断式让它更智慧、可以进行字串处理。自动载入类文件的问题算是终于解决了。但是此时我们又有新的需求:有没有办法自动产生上面的那些代码呢?能不能给你library1资料夹跟library2资料夹,自动进去看到什么类文件就全部想办法用spl_autoload_register记起来好不好?例如下面代码这样:

$please_autoload = array( 'library1', 'library2');
可不可以发明一个工具,去执行$please_autoload这个变数,然后自己想办法载入一切呢?也可能我连php程式码都懒得打了,在Web领域JSON格式更简洁。允许我这样打,好吗?

{
"autoload": [
"library1",
"library2"
]
}
这样可以吗?
可以,所以Composer诞生。Composer对于使用者来说是很透明,但是其背后的理念还是需要了解一下的,其的诞生也不是偶然的,得益于Github的快速发展,PHP语言也越来越现代化,显得更高大上了。其中的关键在于你项目定义的composer.json,可以定义项目需要依赖的包(可能有多个),而依赖的包可能又依赖其他的包(这就是组件的好处),这些都不用你烦心,Composer会自动下载你需要的一切,一切在于composer.json的定义。

Composer的结构

Composer命令行工具:

这个理解就比较简单了,通过使用者定义的Composer.json去下载你需要的代码,假如只是简单的使用Composer,那么掌握一些具体命令就完全可以了。

composer init:使用者可以在自己的项目下创建composer.json以便定义你项目的依赖包,也可以通过composer init交互式的创建composer.json。
composer install:应该是最常用的命令,composer会根据本地的composer.json安装包,将下载的包放入项目下的vendor目录下,同时将安装时候的包版本信息放入到composer.lock,以便锁定版本。其实在install的时候,假如发现composer.lock版本和目前vendor目录下的代码版本是一致的,则Composer会什么也不做,composer.lock的目的就是让你安心在目前这个版本下工作,而不获取最新版本的包。
composer update:那么如何更新composer.lock以便获取到最新版本的包呢?通过这个命令即可更新最新版本的包。
composer config:这个命令还是建议了解下,全局的配置保存在COMPOSER_HOME/config.json,非全局的配置信息则存储在本项目目录下。
composer global:这是一个全局的安装命令,它允许你在COMPOSER_HOME目录下执行Composer的命令,比如install、update。当然你的COMPOSER_HOME要在$PATH环境下。
composer dump-autoload:当你修改项目下的composer.json的文件,并不一定要运行composer update命令进行更新,有的时候可以使用该命令来更新加载器,比如你要引用本地自定义的包(不是来自于packagist),后面会通过实践来说明该命令。
composer require:假如手动或者交互式创建composer.json文件,可以直接使用该命令来安装包。
Autoloading代码加载器:

通过Composer,开发者可以通过多种方式去使用,而其中的关键在于PHP的命名空间概念,以及PSR-4标准的发展,Composer只是根据这二者开发了一个代码自动加载器。

Github:

有了Github,PHP开发人员可以将开源的代码托管在这上面,而Composer的发展源于Github,Composer本质上就是将Github上的代码下载到本地。

Packagist:

对于使用者来说使用的是Composer的命令行工具,那么命令行工具怎么知道有多少包可以被用户使用呢,这主要就是依赖于Packagist,Packagist是Composer主要的一个包信息存储库,包开发者将具体代码托管到Github上,将包信息提交到Packagist上,这样使用者就可以通过Composer去使用。

Composer根据本地定义的composer.json信息去查询Packagist,Packagist根据Composer.json/Package.json信息解析,最终对应到Github仓库,Composer最终下载代码的时候还要依赖于Github仓库上的Composer.json,这里涉及到三种类型的composer.json,含义是不一样的。

Composer.json:

这是Composer的核心,是Composer的规则,上面也提到了三种类型的Composer.json,在使用的时候一定要注意区分,初学的时候不要把它们搞乱。

在本文上面也多次提到了composer.json,比如你希望使用第三方包则需要在本地定义composer.json,Composer安装第三方包后,也会在第三方包目录下发现composer.json,那么这二者都叫composer.json,有什么区别呢?理解这非常的重要。假如你在自己的项目下面定义一个composer.json,则这个包称之为ROOT包,这个composer.json定义你项目需要的条件(比如你的项目可能依赖一个第三方包)。composer.json中有些属性只能被ROOT包使用,比如config属性只在ROOT包中生效。一个资源包是不是ROOT包,取决于它的上下文,比如你git clone ywdblog/phpcomposer,则这时候本地phpcomposer目录就是ROOT包,假如你在本地phpcomposer目录下composer require ywdblog/phpcomposer,则这时候你的项目phpcomposer就是ROOT包。

理解Composer,最重要的是实践,最后也能明白PSR-4和命名空间,也可以尝试将你的项目发布到pckagist.org上。
---------------------
作者:Zhihua_W
来源:****
原文:https://blog.****.net/Zhihua_W/article/details/80345973
版权声明:本文为博主原创文章,转载请附上博文链接!