composer文件结构解析

图片 2

举例来说,假设我们的项目想要使用 monolog
这个日志工具,就需要在composer.json里告诉composer我们需要它:

一、Root Package(根目录包)

首先看下phpcomposer官方的定义,composer是 PHP 用来管理依赖(dependency)关系的工具。你可以在自己的项目中声明所依赖的外部工具库(libraries),Composer
会帮你安装这些依赖的库文件。

{ "require": { "monolog/monolog": "1.*" }}

php composer.phar install

根目录包就是在你的项目的根目录由 composer.json 定义的包。主要就是由
composer.json 来定义你的项目的依赖。

composer可以帮助我们快速安装类库,通过过composer,我们可以使用大量的第三方库,而无需自己造轮子,现在很多流行框架很注重使用composer,因为你可以使用大量优秀的轮子,大大提高效率.

好,现在安装完了,该怎么使用呢?Composer自动生成了一个autoload文件,你只需要引用它

某些字段只能在根目录包的中使用,比如 config
字段,只有根目录包能定义自己的配置。依赖包中的 config
字段是被忽略的。所以 config 字段是 root-only 的。

注意是管理依赖,比如包a需要包b和c当我们安装a的时候并不需要考虑包b和包c的安装,这不仅仅是一个包的安装工具

require '/path/to/vendor/autoload.php';

如果你克隆了其中一个依赖包并在上面工作,那么这个包就是根目录包。composer.json
还是一样的,但上下文不同。

 

然后就可以非常方便的去使用第三方的类库了,是不是感觉很棒啊!对于我们需要的monolog,就可以这样用了:

(注:一个包是不是根目录包,取决于上下文。)

1 安装composer

1.1 下载并安装

官方网址肯定是最优秀的手册,

window安装,使用安装程序

下载并且运行
Composer-Setup.exe,它将安装最新版本的
Composer ,并设置好系统的环境变量,因此你可以在任何目录下直接使用
composer 命令。

linux安装

你可以将此文件放在任何地方。如果你把它放在系统的 PATH
目录中,你就能在全局访问它。

curl -sS | php mv composer.phar
/usr/local/bin/composer

 

1.2 composer的镜像更换

一般情况下,安装包的数据(主要是 zip
文件)一般是从 github.com 上下载的,安装包的元数据是从 packagist.org 上下载的。

然而,由于众所周知的原因,国外的网站连接速度很慢,并且随时可能被“墙”甚至“不存在”。

“Packagist
中国全量镜像”所做的就是缓存所有安装包和元数据到国内的机房并通过国内的
CDN 进行加速,这样就不必再去向国外的网站发起请求,从而达到加速 composer
install以及 composer
update 的过程,并且更加快速、稳定。因此,即使 packagist.org、github.com 发生故障(主要是连接速度太慢和被墙),你仍然可以下载、更新安装包

 

方法一: 修改 composer
的全局配置文件(推荐方式)

打开命令行窗口(windows用户)或控制台(Linux、Mac 用户)并执行如下命令:

composer config -g repo.packagist composer

方法二: 修改当前项目的 composer.json 配置文件:

打开命令行窗口(windows用户)或控制台(Linux、Mac
用户),进入你的项目的根目录(也就是 composer.json 文件所在目录),执行如下命令:

composer config repo.packagist composer

上述命令将会在当前项目中的 composer.json 文件的末尾自动添加镜像的配置信息(你也可以自己手工添加):

“repositories”: { “packagist”: { “type”: “composer”, “url”:
“” } }

 

use MonologLogger;use MonologHandlerStreamHandler;// create a log channel$log = new Logger;$log->pushHandler(new StreamHandler('/path/to/log/log_name.log', Logger::WARNING));// add records to the log$log->addWarning;$log->addError;

二、composer.json 中的各个属性(字段)

2 使用composer

2.1 方法1:通过composer
require命令安装扩展包

composer require monolog/monolog

图片 1

 

安装成功后的目录结构,注意我们在根目录下得到了vender文件夹(包下载后存放位置),composer.json和composer.lock文件(可以说这两个是包管理的指引文件)

图片 2

 

2.2
方法2:编写composer.json文件,然后根据该文件安装扩展包.

composer.json文件包含了项目的依赖和其它的一些元数据。

可以使用 composer init 命令,初始化一个json文件

在 composer.json 文件中指定 require key 的值。告诉 Composer
你的项目需要依赖哪些包。

{ “require”: { “monolog/monolog”: “1.0.*” } }

安装上面的依赖

composer install

和是用composer require 命令一样相同的结果,我们得到了 monolog/monolog
包,并将它下载到 vendor 目录,而且我们也得到了composer.lock文件

 

2.3
关于开发过程中包的管理小建议:

1> 如果你正在使用Git来管理你的项目, 你可能要添加 vendor 到你的
.gitignore 文件中。 你不会希望将所有的代码都添加到你的版本库中。

2>install 命令将创建一个 composer.lock
文件到你项目的根目录中。请提交你应用程序的 composer.lock (包括
composer.json)到你的版本库中

 

2.4 关于如何安装扩展包,进行管理

composer install – 如有 composer.lock 文件,直接安装,否则从
composer.json 安装最新扩展包和依赖;

composer update – 从 composer.json
安装所有最新扩展包和依赖,同时也可以删除依赖,注意是所有,慎用,慎用,慎用;

composer update vendor/package – 从 composer.json
或者对应包的配置,并更新到最新;

composer require new/package – 添加安装 new/package, 可以指定版本,如:
composer require new/package ~2.5.

虽说有多重更新的方案,但是为了项目的稳定性,建议使用require下载和更新扩展包

composer require “monolog/monolog:1.0.*” 通过指定版本可以更新扩展包

 

在这个过程中,Composer做了什么呢?它生成了一个autoloader,再根据各个包自己的autoload配置,从而帮我们进行自动加载的工作。(如果对autoload这部分内容不太了解,可以看我之前的
一篇文章)接下来让我们看看Composer是怎么做的吧。

1、name

3 自动加载

 

如何引用这些库文件。最简单的方式就是require或者include,但这就不够高大上了啊,好在composer可以帮我们解决这个问题。那就是autoload。

那么如何让composer帮我们自动加载这个类呢?

composer 自动加载设置了 4种 加载方式 :

  • files
  • classmap
  • PSR-0
  • PSR-4

并推荐使用 PSR-4 规范

下面分别来探讨,在composer.json定义这几种加载方式:

 

3.1
使用Files方式(ps:通常作为函数库的载入方式(而非类库))

1> files 就是直接简单粗暴的加载文件。在 composer 执行 install
等操作时, composer 会把文件中的配置存储在
vendor/composer/autoload_static.php 文件中的生成一个 $files 数组。

 

2> composer.json 配置

“autoload”: { “files”: [“Lionis/Cool.php”] }

 

3>
files键对应的值是一个数组,数组元素是文件的路径,路径是相对于应用的根目录。

 

3.2 Classmap方式自动加载

1> classmap 通过配置指定的目录和文件,在 composer 执行 install
等操作时, composer 会去扫描对应的目录下以 .php 结尾的文件中的 class
,并存储在 vendor/composer/autoload_classmap.php 文件中的返回数组中。

 

2> composer.json 配置

“autoload”: { “classmap”: [ “Lionis/”, ] }

 

3> 如果 Lionis 下有一个叫
Cool的文件,当程序需要Cool类时,compoer的自动加载类通过查找Cool类所在的文件,然后再将改文件include进来。

 

 

3.3 PSR-0加载方式

1>
要求命名空间和目录层层对应,且可以使用 _
作为路径分隔符,但是这会导致目录结果变得过深,在 composer 执行 install
等操作时, composer 会把文件中的配置存储在
vendor/composer/autoload_psr0.php 文件中的返回数组中。

 

2> composer.json 配置

“autoload”: { “psr-0”: { “Very\Good”: “vendorLionis” } }

 

在调用 use VeryGoodLoveSomeClass的时候,实际加载目录为
vendor/Lionis/Very/Good/Love/SomeClass.php

 

3.4 PSR-4加载方式

1> 与 PSR-0 不同的是,取消掉了 _ 作为分隔符和目录结构。在 composer
执行 install 等操作时, composer 会把文件中的配置存储在
vendor/composer/autoload_psr4.php 文件中的返回数组中。

 

2> composer.json 配置

“autoload”: { “psr-4”: { “Very\Good”: “vendorLionis” } }

 

在调用 use VeryGoodLoveSomeClass的时候,实际加载目录为
vendor/Lionis/Love/SomeClass.php,发现我们并不一定要有Very/Good文件层次

 

小结

composer 通过使用 composer.json ,用 json
的格式来指定我们需要自动加载的规则 ,当我们在 composer 执行 install
等操作时,composer会根据这些规则自动生成相应规则的自动加载文件,并存储在vendor/composer下的相应文件中,我们只要在入口文件引入
vendor/autoload.php 就能很方便的便能使用自动加载 。

 

 

//关于自动加载,推荐文章

 

简单命令

composer require cuab/phpcrawl

composer init 初始化一个json文件

composer install 安装json中的依赖

composer update 更新json中的依赖,可以删除相应的依赖

composer search phpcrawl

composer show –all cuab/phpcrawl

 

 

 

对于第三方包的自动加载,Composer提供了四种方式的支持,分别是
PSR-0和PSR-4的自动加载,生成class-map,和直接包含files的方式。

包的名字。由供应方(vendor)名和项目名组成,用 / 分隔。

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

在发布包的时候需要填。

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

2、description

key和value就定义出了namespace以及到相应path的映射。按照PSR-4的规则,当试图自动加载
“Foo\Bar\Baz” 这个class时,会去寻找 “src/Bar/Baz.php”
这个文件,如果它存在则进行加载。注意,
“Foo\”并没有出现在文件路径中,这是与PSR-0不同的一点,如果PSR-0有此配置,那么会去寻找

对包的一个简短描述,通常是一行的长度。

“src/Foo/Bar/Baz.php”

在发布包的时候需要填。

另外注意PSR-4和PSR-0的配置里,”Foo\”结尾的命名空间分隔符必须加上并且进行转义,以防出现”Foo”匹配到了”FooBar”这样的意外发生。

3、version

在composer安装或更新完之后,psr-4的配置换被转换成namespace为key,dir
path为value的Map的形式,并写入生成的 vendor/composer/autoload_psr4.php
文件之中。

包的版本。

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

格式必须是 X.Y.Z,选择性后缀:-dev、-alphaN、-betaN、-RCN。

最终这个配置也以Map的形式写入生成的

4、type

vendor/composer/autoload_namespaces.php

包的类型,默认为 library。

Class-map方式,则是通过配置指定的目录或文件,然后在Composer安装或更新时,它会扫描指定目录下以.php或.inc结尾的文件中的class,生成class到指定file
path的映射,并加入新生成的 vendor/composer/autoload_classmap.php
文件中,。

包类型用于定制安装逻辑。如果你的包的安装需要一些特殊的逻辑,你可以定义一个定制的类型。它可以是一个
symfony-bundle 的类型,或者 wordpress-plugin,或者
typo3-module。这些类型将被特定的项目所用,它们将提供安装器来安装这些类型的包。

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

Composer 支持 3 种类型:

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

library:默认值。它将复制文件到 vendor 目录。

‘BaseController’ => $baseDir . ‘/src/BaseController.php’

project:它表示这是个项目,而不是库。比如像 Symfony 标准版这种应用。

Files方式,就是手动指定供直接加载的文件。比如说我们有一系列全局的helper
functions,可以放到一个helper文件里然后直接进行加载

metapackage:一个含有依赖的空包,能触发安装,但不包含文件,不会向文件系统写任何东西。

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

composer-install:为其他的定制类型的包提供安装器的包。

它会生成一个array,包含这些配置中指定的files,再写入新生成的

5、keywords

vendor/composer/autoload_files.php

一个与包相关的关键词数组。用于包的搜索和过滤。

文件中,以供autoloader直接进行加载。

可选。

下面来看看composer autoload的代码吧

6、homepage

 $path) { $loader->set; } $map = require __DIR__ . '/autoload_psr4.php'; foreach ($map as $namespace => $path) { $loader->setPsr4; } $classMap = require __DIR__ . '/autoload_classmap.php'; if  { $loader->addClassMap; } $loader->register; $includeFiles = require __DIR__ . '/autoload_files.php'; foreach ($includeFiles as $file) { composerRequire73612b48e6c3d0de8d56e03dece61d11; } return $loader; }}function composerRequire73612b48e6c3d0de8d56e03dece61d11{ require $file;}

项目的网站 URL。

首先初始化ClassLoader类,然后依次用上面提到的4种加载方式来注册/直接加载,ClassLoader的一些核心代码如下:

可选。

/** * @param array $classMap Class to filename map */ public function addClassMap { if  { $this->classMap = array_merge($this->classMap, $classMap); } else { $this->classMap = $classMap; } } /** * Registers a set of PSR-0 directories for a given prefix, * replacing any others previously set for this prefix. * * @param string $prefix The prefix * @param array|string $paths The PSR-0 base directories */ public function set { if  { $this->fallbackDirsPsr0 =  $paths; } else { $this->prefixesPsr0[$prefix[0]][$prefix] =  $paths; } } /** * Registers a set of PSR-4 directories for a given namespace, * replacing any others previously set for this namespace. * * @param string $prefix The prefix/namespace, with trailing '\' * @param array|string $paths The PSR-4 base directories * * @throws InvalidArgumentException */ public function setPsr4 { if  { $this->fallbackDirsPsr4 =  $paths; } else { $length = strlen; if ('\' !== $prefix[$length - 1]) { throw new InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); } $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; $this->prefixDirsPsr4[$prefix] =  $paths; } } /** * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not */ public function register { spl_autoload_register(array, true, $prepend); } /** * Loads the given class or interface. * * @param string $class The name of the class * @return bool|null True if loaded, null otherwise */ public function loadClass { if ($file = $this->findFile { includeFile; return true; } } /** * Finds the path to the file where the class is defined. * * @param string $class The name of the class * * @return string|false The path if found, false otherwise */ public function findFile { //这是PHP5.3.0 - 5.3.2的一个bug 详见https://bugs.php.net/50731 if  { $class = substr; } // class map 方式的查找 if (isset($this->classMap[$class])) { return $this->classMap[$class]; } //psr-0/4方式的查找 $file = $this->findFileWithExtension; // Search for Hack files if we are running on HHVM if ($file === null && defined { $file = $this->findFileWithExtension; } if  { // Remember that this class does not exist. return $this->classMap[$class] = false; } return $file; } private function findFileWithExtension { // PSR-4 lookup $logicalPathPsr4 = strtr($class, '\', DIRECTORY_SEPARATOR) . $ext; $first = $class[0]; if (isset($this->prefixLengthsPsr4[$first])) { foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { if (0 === strpos { foreach ($this->prefixDirsPsr4[$prefix] as $dir) { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { return $file; } } } } } // PSR-4 fallback dirs foreach ($this->fallbackDirsPsr4 as $dir) { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { return $file; } } // PSR-0 lookup if (false !== $pos = strrpos { // namespaced class name $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); } else { // PEAR-like class name $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; } if (isset($this->prefixesPsr0[$first])) { foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { if (0 === strpos { foreach  { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { return $file; } } } } } // PSR-0 fallback dirs foreach ($this->fallbackDirsPsr0 as $dir) { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { return $file; } } // PSR-0 include paths. if ($this->useIncludePath && $file = stream_resolve_include_path { return $file; } }/** * Scope isolated include. * * Prevents access to $this/self from included files. */function includeFile{ include $file;}

7、time

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

可选。

8、license

包的许可证。可以是字符串或字符串数组。

可选,但强烈建议加上。

9、authors

包的作者。是个对象数组。

每个 author 对象有这些属性:

name:作者名字

email:作者邮箱

homepage:作者网站 URL

role:作者在项目中的角色(如:developer 或 translator)

10、support

各种关于该项目如何获取支持的信息。包含这些属性:

email:获取支持的邮箱

issues:问题跟踪的 URL

forum:论坛的 URL

wiki:Wiki 的 URL

irc:IRC 的频道

source:查看或下载源码的 URL

可选。

11、Package links

依赖包的映射表,由包名映射版本约束。如:

{

    “require”: {

        “monolog/monolog”: “1.0.*”

    }

}

(1)require

列出包所依赖的包。除非这些依赖已经存在,否则这个包不会被安装。

(2)require-dev(root-only)

列出开发这个包(或跑测试等等)所依赖的包。在使用 install
命令时,只有带上 “–dev” 参数才能安装 dev 包。在使用 update 命令时,带上
“–no-dev” 则不更新。

(3)conflict

列出包会和哪些包发生冲突。它们将不被允许和你的包一起安装。如果约束了版本,则只会针对特定的版本。

(4)replace

列出哪些包要被这个包替代。

(5)provide

这个包所推荐的包列表。这个对公共接口最有用,一个包可以依赖一个虚拟的
logger 包,而实现 logger 接口的库可以放到 provide 字段中。

12、suggest

建议一些能让这个包工作的更好或得到增强的包列表。这些信息只在包安装完成时给出,暗示用户可以添加更多包,虽然不是必须要安装的。

格式是,包名映射文字说明,如:

{

    “suggest”: {

        “monolog/monolog”: “Allows more advanced logging of the
application flow”

    }

}

13、autoload

提供给 PHP autoloader 的自动加载映射。

目前支持的有:PSR-0 自动加载规范,classmap 生成器,还有 files。

PSR-0
是比较推荐的,因为它的优秀的扩展性(在添加新的类的适合,不需要重新生成自动加载器)。

You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图