所有的依赖都定义在composer.json中,手册中给出了一些基本用法和例子。你可能已经注意到,在指定版本号的时候,我们并不一定要指明一个精确的版本。那么就有可能发生这么一个情况,对于同一份composer.json,我们在不同时刻拉取到的依赖文件可能不同(因为composer会在满足条件的情况下去拉取最新的那份依赖),从而导致一些异常情况。composer update和composer install正是为了解决这个问题而出现的。
当你执行composer update的时候,composer会去读取composer.json中指定的依赖,去分析他们,并且去拉取符合条件最新版本的依赖。然后他会把所拉取到的依赖放入vendor目录下,并且把所有拉取的依赖的精确版本号写入composer.lock文件中。
composer install所执行的事情非常类似,只在第一步的时候有差别。当你本地如果已经存在一份composer.lock时,它将会去读取你的composer.lock而非composer.json,并且以此为标准去下载依赖。当你本地没有composer.lock的时候,它所做的事情和composer update其实并没有区别。
这意味着,只要你本地有一份composer.lock,你就可以保证无论过去了多久,你都能拉到相同的依赖。而如果你把它纳入你的项目的版本控制中,那么你就可以确保你项目中的每一个人、每一台电脑,不管什么系统,都能拉取到一模一样的依赖,以减少潜在的依赖对部署的影响。当然,请记得,你应该使用的命令是composer install。
那什么时候该使用composer update呢?当你修改了你的依赖关系,不管是新增了依赖,还是修改了依赖的版本,又或者是删除了依赖,这时候如果你执行composer install的时候,是不会有任何变更的,但你会得到一个警告信息
Warning: The lock file is not up to date with the latest changes in composer.json. You may be getting outdated dependencies. Run update to update them.
package引用和版本
项目下composer.json的写法, 如何引入包得写法
{
“require”:{
“mustache/mustache”:”2.9.0”,//这里就是写入包名字与具体版本号
//前面这个是vendor目录的包得vendor name
//然后第2个同名的就对应包的名字,一般来说是这样写法
}
}
引入版本时候~号说明
例子:~2.8.1,那么范围区间是2.8.1 to 2.9.0
例子:~2.8,那么范围区间就变成 2.8 to 3.0
~号:代表一个区间,0–9
引入版本时候^号说明
例子:^2.8,那么代表是,2.8 到 3.0,也就是说最大得版本号+1的点0版本,也就是2.8的2+1,.8变成.0
例子:今天实践了下,^号也可以理解成为安装最新版本,下面例子就出现最新版的包了
{
“require”:{
“mustache/mustache”:”^2.7”
}
}
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
require_once DIR . ‘/composer/autoload_real.php’;
return ComposerAutoloaderInit23bbeae59271b037728c906bcb04be61::getLoader();
第二步:查看autoload_real.php,目录:vendor/composer/autoload_real.php
通过getLoader方法里的一个foreach进行注册
$map = require DIR . ‘/autoload_namespaces.php’;
foreach ( $map as $namespace => $path ) {
$loader->set($namespace,$path);
}
第三步:查看autoload_namespaces.php,目录:vendor/composer/autoload_namespaces.php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(FILE));
$baseDir = dirname($vendorDir);
return array(
‘Mustache’ => array($vendorDir . ‘/mustache/mustache/src’),
//src目录下就按照以上的命名空间来操作
);
第四步:查看依赖包目录下得composer.json文件,看它通过那个命名空间规范来加载
目录:mustache/composer.json
通过psr-0规范标准
“autoload”: {
“psr-0”: { “Mustache”: “src/” }
}
整条自动加载流程:
引入自动加载文件 autoload.php
自动执行autoload_real.php中得方法getLoader()
方法中调用了autoload_namespaces.php进行返回一个数组,到此自动加载命名空间 基本结束
namespaces文件执行的命名空间标准需要查看依赖包下得composer.json文件
05:Find A Package
在packagist.org进行搜索依赖包
再终端可以使用命令 :composer serach <包名>
显示具体信息终端命令:composer --all <包名>
06:使用composer创建项目
常见命令 :composer create-project
composer创建项目终端命令:composer create-project <原始名字>/<默认名字> <别名> <版本号>
07: Understanding Require Dev
composer一个特点:require-dev--本地开发使用到得package
如果下载一个项目,并不需要dev环境中得package可以使用:composer install --no-dev来操作
所以上传自己项目时候需要包含composer.lock这个文件
08:composer运行shell命令
网址:getcomposer.org/doc/articles/scripts.md下得command events看到具体命令
只需要在composer.json文件加上scipts这样的引导数组即可,下面例子参考:
"scripts":{
"post-install-cmd":"echo 'hello'"
}
09:发布自己的Package
第一步:登陆github,创建项目
第二步:终端git clone 项目地址
第三步:进入项目目录,创建composer.json文件:执行命令composer init即可
第四步:根据提示填写完毕穿件composer.json
package name
description
author
minimum stability
package type
license
第五步命令:git add .
第六步命令:git commit -m"更改的描述"
第七步命令:git push
第八步:发布到packaglist.org,登陆自己的id
第九步:点击右上角submit,然后粘贴github连接后,再点击check
第十步:添加自动更新webhook
到 github项目,点击settings
点击左边导航webhooks & services
点击右边的add services
搜索package
填写user token,token可以再packagist得profile找到
粘贴token,然后addservice
然后点击生成出来的package出现画面
点击test service,出现ok表示成功
备注:绑定完成后,当你git提交更新后就会同步到package那边了
使用ali镜像
composer config repo.packagist composer https://mirrors.aliyun.com/composer/
$ composer install
1/12: https://mirrors.aliyun.com/composer/p/provider-2019-07$9335bea6ef0c2f837b62b202407c083f6f80f1a29af254d28713fdc163600112.json
composer -vvv require monolog/monolog:1.0.*
:80/artifactory/api/composer/composer-github/p/alibabacloud/sdk.json” file could not be downloaded: php_network_ge
taddresses: getaddrinfo failed: nodename nor servname provided, or not known
failed to open stream: php_network_getaddresses: getaddrinfo failed: nodename nor servname provided, or not known
本地镜像和全局镜像同时存,但是冲突了,全局镜像无法链接拉取
composer clear cache
$mv ~/.composer/ ~/.composer.bak
composer.json增加
“require”: {
“alibabacloud/sdk”: “^1.7”,
“monolog/monolog”: “1.0.*”
}
生成文件:
composer.lock vendor
spl_autoload_register ([ callable $autoload_function [, bool $throw = true [, bool $prepend = false ]]] ) : bool
autoload_function
欲注册的自动装载函数。如果没有提供任何参数,则自动注册 autoload 的默认实现函数spl_autoload()。
throw
此参数设置了 autoload_function 无法成功注册时, spl_autoload_register()是否抛出异常。
prepend
如果是 true,spl_autoload_register() 会添加函数到队列之首,而不是队列尾部。
autoload_real.php加载过程
public static function getLoader()
先注册了一个loader 用于加载 \Composer\Autoload\ClassLoader()
spl_autoload_register(array(‘ComposerAutoloaderInit0de2ad01cd2d49322d48c96d21b4cf31’, ‘loadClassLoader’), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array(‘ComposerAutoloaderInit0de2ad01cd2d49322d48c96d21b4cf31’, ‘loadClassLoader’));
require_once DIR . ‘/autoload_static.php’;
call_user_func(\Composer\Autoload\ComposerStaticInit0de2ad01cd2d49322d48c96d21b4cf31::getInitializer($loader));
$loader->register(true); //如果文件存在就require
$includeFiles = Composer\Autoload\ComposerStaticInit0de2ad01cd2d49322d48c96d21b4cf31::$files;
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire0de2ad01cd2d49322d48c96d21b4cf31($fileIdentifier, $file);
}
首先在 autoload.php中调用ComposerAutoloaderInit1215780529014c2b50a6fca7ce889273::getLoader()方法,getLoader()首先判断当前𝑙𝑜𝑎𝑑𝑒𝑟是不是𝑛𝑢𝑙𝑙,如果不为𝑛𝑢𝑙𝑙就直接返回,否则就初始化一个𝐶𝑙𝑎𝑠𝑠𝐿𝑜𝑎𝑑𝑒𝑟类给赋值给loader,接着将autoload_namespaces.php、autoload_psr4.php、autoload_classmap.php文件中的内容加入到$loader中对应的数组中,然后给注册loadClass函数,将autoload_files.php中的所有路径所示的文件都包含进来,当在new一个类的时候如果没有找到相关的类就会触发这个loadClass函数,在loadClass()又调用了findFile()去查找相应的文件,找到相应文件后就会返回该文件,然后loadClass调用includeFile()方法将该文件include进去,否则findFile返回false,这样就完成了自动加载
indFile()函数先在classMap中查找,如果找不到的话就会尝试在apcu缓存中查找,如果还是找不到的话就会调用findFileWithExtension()函数查找,如果找到了就会将该文件加到apcu缓存,如果找不到的话就会在missingClasses数组中设一个标记表示识这个类找不到
findFileWithExtension()方法根据之前通过𝑙𝑜𝑎𝑑𝑒𝑟−>𝑠𝑒𝑡(namespace, 𝑝𝑎𝑡ℎ)和loader->setPsr4(𝑛𝑎𝑚𝑒𝑠𝑝𝑎𝑐𝑒,path)方法设置的信息找出类文件的路径信息
在上面有的地方用到了 spl_autoload_register和spl_autoload_unregister函数
spl_autoload_register函数
spl_autoload_register — 注册给定的函数作为 __autoload 的实现,
bool spl_autoload_register ([ callable 𝑎𝑢𝑡𝑜𝑙𝑜𝑎𝑑𝑓𝑢𝑛𝑐𝑡𝑖𝑜𝑛[,𝑏𝑜𝑜𝑙throw = true [, bool $prepend = false ]]] )
prepend
如果是 true,spl_autoload_register() 会添加函数到队列之首,而不是队列尾部。
如果在你的程序中已经实现了__autoload()函数,它必须显式注册到__autoload()队列中。因为 spl_autoload_register()函数会将Zend Engine中的__autoload()函数取代为spl_autoload()或spl_autoload_call()