这一次,真正掌握composer
<div><div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="991" data-height="513"><img src="//upload-images.jianshu.io/upload_images/1864602-4f4ede522ec84280.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/991/format/webp"></div>
</div>
<div class="image-caption">思维导图</div>
</div>
<h1>composer是现代PHP的基石</h1>
<p>现代高级编程语言,依赖管理工具是必不可少的。Java有Maven,Python有pip,Nodejs有npm, 而在composer出现之前,PHP只有被广为诟病的Pear, 由于Pear实在太难用,很少PHP开发者用到这个工具。以致于PHP的开发生态很糟糕。</p>
<p>连一个像样的依赖管理工具都没有,让PHP这门占据了web网站开发�主流市场的语言很尴尬。开发过程中,要用到第三方的类库,需要去下载zip包,然后解压,放到相应的目录,处理好命名空间,自动加载的问题,如果这个第三方包还有其他依赖项,还要再次重复这个流程,看着隔壁家python和node.js一个命令行就搞定,显得php开发人员的操作既原始又滑稽。</p>
<p>这场面,好比:</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1142" data-height="1466"><img src="//upload-images.jianshu.io/upload_images/1864602-10741cd122775321.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000/format/webp"></div>
</div>
<div class="image-caption">依赖管理工具大比拼</div>
</div>
<p>所幸,金光闪闪的composer驾着七彩祥云来了,PHP终于有了真正意义的依赖管理工具。可以说,composer是现代PHP的基石。</p>
<p>composer解决了项目的依赖关系,且实现了自动加载。开发人员只需要几个命令行,就能获取其他开发者的包,PHP开发工作因此变得如同堆积木,可以根据业务的需求,快速方便地拆解组合代码。</p>
<p>奇怪的是,即使compoer已经诞生好些年了,而且所有主流框架都支持composer,可竟然还有不少PHP开发者不用这个工具。甚至还有人觉得composer加大了PHP的学习难度。</p>
<p>持有这种想法的人,就好像是一辈子都用纸笔手工记账,有朝一日,给他配置了电脑,跟他演示了excel是如何地强大。他不为新事物的强大感到震撼惊喜,而是蹙眉不满地说:“这东西太难学了,我还是习惯用纸笔”。</p>
<p>对于持有这种想法的人,我只能两手一摊。心态衰老的年轻人,如果他的内心一直在装睡,任谁也叫不醒。但时代的步伐可不会因为他们的拉后腿而停止前进,只会把他们远远甩在身后...</p>
<h1>初识composer</h1>
<p>composer的安装步骤,在composr中文社区有详细的说明,点击查看</p>
<h2>安装流程</h2>
<p>安装的流程很简单,归结为以下几步:</p>
<pre class="hljs bash"><code class="bash">php -r <span class="hljs-string">"copy('https://install.phpcomposer.com/installer', 'composer-setup.php');" <span class="hljs-comment"># 下载安装脚本 - composer-setup.php - 到当前目录
php composer-setup.php <span class="hljs-comment"># 执行安装过程
php -r <span class="hljs-string">"unlink('composer-setup.php');" <span class="hljs-comment"># 删除安装脚本
sudo mv composer.phar /usr/<span class="hljs-built_in">local/bin/composer <span class="hljs-comment"># 全局安装
composer config -g repo.packagist composer https://packagist.phpcomposer.com <span class="hljs-comment"># 更换国内镜像源
</span></span></span></span></span></span></span></span></code></pre>
<p>安装完成后,查看composer版本</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1354" data-height="746"><img src="//upload-images.jianshu.io/upload_images/1864602-b855abd6750b4c5f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000/format/webp"></div>
</div>
<div class="image-caption">composer</div>
</div>
<h2>第一次使用</h2>
<p>接下来,我们用composer来安装第一个包</p>
<p>以<code>monolog</code>包为例,这个包可以让开发者很方便地将日记写入到文件、数据库或其他储存介质中。</p>
<ol>
<li>在项目根目录新建<code>composer.json</code>文件,写入以下内容</li>
</ol>
<pre class="hljs json"><code class="json">{
<span class="hljs-attr">"require": {
<span class="hljs-attr">"monolog/monolog": <span class="hljs-string">"1.2.*"
}
}
</span></span></span></code></pre>
<ol start="2">
<li>执行<code>composer install</code>指令安装包依赖</li>
</ol>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1754" data-height="390"><img src="//upload-images.jianshu.io/upload_images/1864602-86f686d51410c326.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000/format/webp"></div>
</div>
<div class="image-caption">composer install</div>
</div>
<ol start="3">
<li>使用包进行开发</li>
</ol>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1170" data-height="380"><img src="//upload-images.jianshu.io/upload_images/1864602-4c6f69d3389831ba.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000/format/webp"></div>
</div>
<div class="image-caption">目录结构</div>
</div>
<p>composer已经为我们下载了<code>monolog</code>包,且生成了<code>autoload.php</code>自动加载文件</p>
<p>新建<code>monolog.php</code>文件,内容如下:</p>
<pre class="hljs php"><code class="php"><span class="hljs-meta"><?php
<span class="hljs-keyword">require <span class="hljs-string">'vendor/autoload.php';
<span class="hljs-keyword">use <span class="hljs-title">Monolog\<span class="hljs-title">Logger;
<span class="hljs-keyword">use <span class="hljs-title">Monolog\<span class="hljs-title">Handler\<span class="hljs-title">StreamHandler;
<span class="hljs-comment">// create a log channel
$log = <span class="hljs-keyword">new Logger(<span class="hljs-string">'name');
$log->pushHandler(<span class="hljs-keyword">new StreamHandler(<span class="hljs-string">'monolog.log', Logger::WARNING));
<span class="hljs-comment">// add records to the log
$log->warn(<span class="hljs-string">'警告日志');
$log->err(<span class="hljs-string">'错误日志');
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
<p>运行脚本:</p>
<pre class="hljs php"><code class="php">learnComposerphp monolog.php
</code></pre>
<p>生成了日志文件<code>monolog.log</code></p>
<pre class="hljs css"><code class="css"><span class="hljs-selector-attr"> <span class="hljs-selector-tag">name<span class="hljs-selector-class">.WARNING: 警告日志 <span class="hljs-selector-attr">[] <span class="hljs-selector-attr">[]
<span class="hljs-selector-attr"> <span class="hljs-selector-tag">name<span class="hljs-selector-class">.ERROR: 错误日志 <span class="hljs-selector-attr">[] <span class="hljs-selector-attr">[]
</span></span></span></span></span></span></span></span></span></span></code></pre>
<p>只需一个配置文件<code>composer.json</code>,一行指令<code>composer install</code>,代码中引入<code>autoload.php</code>,即可完美地使用第三方包。接下来分析composer的包管理规范</p>
<h1>composer包管理规范</h1>
<p>什么是包?只要存在<code>composer.json</code>文件的代码都可以称之为一个包。</p>
<h2>包名称</h2>
<p>包名称由作者+项目名称组成。有些包作者名与项目名是相同的,如<code>mustache/mustache</code></p>
<p>包名称一定要加上作者,避免冲突。如,同样的是小龙女这个角色,不同人演绎的效果完全不同。如果你只是说你要看小龙女,可能给你的是一个陈妍希版本的小笼包,而不是你一直仰慕的仙女刘亦菲。</p>
<p>那么,我们怎么根据一个包的项目名去获取包的信息呢?以<code>mustache</code>包为例:</p>
<ol>
<li>在packagist查找</li>
</ol>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1740" data-height="1272"><img src="//upload-images.jianshu.io/upload_images/1864602-ff2f59bb4b34d0e9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000/format/webp"></div>
</div>
<div class="image-caption">搜索包</div>
</div>
<p>点击进入包信息详情页,可以看到包的安装方法以及版本信息</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1862" data-height="612"><img src="//upload-images.jianshu.io/upload_images/1864602-eaf584348b4cf636.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000/format/webp"></div>
</div>
<div class="image-caption">安装包</div>
</div>
<blockquote>
<p>除了在<code>composer.json</code>中写包的安装信息,还可以通过<code>composer require mustache/mustache</code>这种方式直接安装</p>
</blockquote>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="2410" data-height="734"><img src="//upload-images.jianshu.io/upload_images/1864602-16491fb7c3cbcb0e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000/format/webp"></div>
</div>
<div class="image-caption">包信息</div>
</div>
<ol start="2">
<li>用<code>composer search</code>指令查找</li>
</ol>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1360" data-height="498"><img src="//upload-images.jianshu.io/upload_images/1864602-2cba621fe408d2c7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000/format/webp"></div>
</div>
<div class="image-caption">composer search</div>
</div>
<p>查看包的具体信息 <code>composer show mustache/mustache --all</code></p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1838" data-height="436"><img src="//upload-images.jianshu.io/upload_images/1864602-71dbef7426ad717b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000/format/webp"></div>
</div>
<div class="image-caption">composer show</div>
<div class="image-caption">
<h2>包版本</h2>
<p>在<code>composer.json</code>中声明安装包时,需要指定包的版本,�版本号的指定有多种格式:</p>
<ul>
<li>确定的版本号</li>
</ul>
<p>格式:<code>1.0.2</code></p>
<p>最简单的指定方式,无歧义</p>
<ul>
<li>在一定范围的版本号</li>
</ul>
<p>可以定义多个范围,用逗号隔开,这将被视为一个逻辑AND处理。一个管道符号|将作为逻辑OR处理。 AND 的优先级高于 OR</p>
<p><code>>=1.0</code>: 大于或等于1.0版本</p>
<p><code>>=1.0,<2.0</code>: 大于或等于1.0,且小于2.0</p>
<p><code>>=1.0,<1.1|>=1.2</code>: 大于或等于1.0且等于1.1,或者大于等于1.2</p>
<ul>
<li>通配符</li>
</ul>
<p><code>1.0.*</code>: 只要满足以1.0开头的版本号均可</p>
<ul>
<li><code>~</code>下一个重要版本</li>
</ul>
<p>~1.2 相当于 >=1.2,<2.0</p>
<p>~1.2.3 相当于 >=1.2.3,<1.3</p>
<ul>
<li><code>^</code>大于指定的版本</li>
</ul>
<p>以下用实例演示版本号的区别:</p>
<p>清空根目录,<code>composer.json</code>内容为:</p>
<pre><code class="json">{
"require": {
"mustache/mustache": "2.6.0"
}
}
</code></pre>
<p>执行<code>composer install</code></p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1094" data-height="392"><img src="https://upload-images.jianshu.io/upload_images/1864602-c68ba35ea1168633.png"></div>
</div>
<div class="image-caption">指定版本</div>
</div>
<p>接下来,删除<code>vendor</code>目录,将版本号改为<code>~2.6.0</code>, 执行<code>composer install</code></p>
<p>此时,会发现版本号并没有变化</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1714" data-height="288"><img src="https://upload-images.jianshu.io/upload_images/1864602-d3c26954cf4320f4.png"></div>
</div>
<div class="image-caption">composer install 无效</div>
</div>
<p>这是因为当我们第一次执行<code>composer install</code>,会生成<code>composer.lock</code>文件,这个文件记录了包的指定版本</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1368" data-height="820"><img src="https://upload-images.jianshu.io/upload_images/1864602-8205dd1161f047cb.png"></div>
</div>
<div class="image-caption">版本锁定</div>
</div>
<p>当我们再次执行<code>composer install</code>时,�composer会先去<code>composer.lock</code>中检查有没有相应的包信息,如果有,以<code>composer.lock</code>的版本为准。如果我们要跳过<code>composer.lock</code>的限制,需要改用<code>composer update</code>指令</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1278" data-height="348"><img src="https://upload-images.jianshu.io/upload_images/1864602-3eed17743739da7b.png"></div>
</div>
<div class="image-caption">composer update</div>
</div>
<p>此时,我们看到,版本已经更新为<code>2.6.1</code></p>
<p>最后再试下将版本号改为<code>^2.6.0</code>, 执行<code>composer update</code></p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1182" data-height="368"><img src="https://upload-images.jianshu.io/upload_images/1864602-91894f44a1eb7da5.png"></div>
</div>
<div class="image-caption">版本更新</div>
</div>
<p>此时,已经更新到最新版本号</p>
<h1><code>composer.lock</code>锁文件</h1>
<p><code>composer.json</code>在指定版本时,不一定是精确指定,很多时候是使用范围指定,只有当我们安装了包,才知道最终安装了哪个版本。那么问题来了,如果我们半年后再根据<code>composer.json</code>来安装包,可能有些包的版本已经升级了,且向下不兼容,这就有可能导致程序报错。为避免这种问题,在执行<code>composer install</code>之后,composer会生成<code>composer.lock</code>锁文件。</p>
<p>在锁文件中可以看到完整的包信息,包括包的版本号。</p>
<p><code>composer install</code>命令会先检查锁文件是否存在,如果存在,它将下载<code>composer.lock</code>指定的版本(忽略 <code>composer.json</code> 文件中的定义)</p>
<p>如果在<code>composer.json</code>中修改了版本号,必须执行<code>composer update</code>命令,这个命令会根据<code>composer.json</code>的定义安装包,并更新<code>composer.lock</code>文件</p>
<p>锁文件非常重要!必须将<code>composer.lock</code>文件上传到代码仓库,这样才能保证团队各成员所安装的包版本是一致的。</p>
<h1>创建项目</h1>
<p>composer通过<code>create-project</code> 可以直接创建一个完整的项目,将包所在的代码仓库clone下来</p>
<p>以创建laravel项目为例:</p>
<pre><code class="bash">learnComposercomposer create-project laravel/laravel Laravel --prefer-dist "5.5.*"
</code></pre>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="846" data-height="558"><img src="https://upload-images.jianshu.io/upload_images/1864602-a01e8e329b52c448.png"></div>
</div>
<div class="image-caption">create-project</div>
</div>
<h1>开发与生产环境分开</h1>
<p>有些包我们仅需要在本地安装,生产环境并不需要,可以在<code>composer.json</code>中通过<code>require-dev</code>进行声明,如:</p>
<p><code>composer install --no-dev</code> 会忽略<code>require-dev</code>所声明的包</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="759" data-height="180"><img src="https://upload-images.jianshu.io/upload_images/1864602-91c7e0d3e33ddc15.png"></div>
</div>
<div class="image-caption">�--no-dev</div>
</div>
<p><code>composer install</code>会将<code>require-dev</code>声明的包一并获取</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="935" data-height="255"><img src="https://upload-images.jianshu.io/upload_images/1864602-9cc813d8ec9be953.png"></div>
</div>
<div class="image-caption">install</div>
</div>
<h1>自定义脚本</h1>
<p>在Laravel的<code>composer.json</code>文件中,有这么一段声明:</p>
<pre><code class="json">"scripts": {
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
],
"post-create-project-cmd": [
"@php artisan key:generate"
],
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover"
]
},
</code></pre>
<p>表示在执行<code>composer install</code>时的相应阶段,会自动触发运行脚本</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="780" data-height="285"><img src="https://upload-images.jianshu.io/upload_images/1864602-d853695e0d4131c9.png"></div>
</div>
<div class="image-caption">触发脚本</div>
</div>
<h1>发布自己的包</h1>
<ol>
<li>github是新建一个仓库</li>
</ol>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1091" data-height="554"><img src="https://upload-images.jianshu.io/upload_images/1864602-4fd0dd1e21c2e7ba.png"></div>
</div>
<div class="image-caption">github仓库</div>
</div>
<ol start="2">
<li>创建<code>composer.json</code>文件</li>
</ol>
<p>在项目根目录执行<code>composer init</code>,生成<code>composer.json</code>配置文件</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1200" data-height="726"><img src="https://upload-images.jianshu.io/upload_images/1864602-14f4406ecf2fcbc4.png"></div>
</div>
<div class="image-caption">composer init</div>
</div>
<ol start="3">
<li>在packagist提交github仓库地址</li>
</ol>
<p>在packagist注册账号,然后登录。</p>
<p>提交github仓库地址</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1191" data-height="510"><img src="https://upload-images.jianshu.io/upload_images/1864602-29932404b10f7ccd.png"></div>
</div>
<div class="image-caption">submit</div>
</div>
<p>包创建成功</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1315" data-height="814"><img src="https://upload-images.jianshu.io/upload_images/1864602-133dc09a0285e61b.png"></div>
</div>
<div class="image-caption">创建成功</div>
</div>
<p>如果用的是国内的镜像,暂时还不能拉取,需要等国内镜像同步成功后才能拉取</p>
<ol start="4">
<li>设置自动同步</li>
</ol>
<p>如果要实现当github仓库代码更新就触发包的自动更新,需要进行以下设置</p>
<p>在github中添加packagist服务</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1116" data-height="474"><img src="https://upload-images.jianshu.io/upload_images/1864602-ee9397b1fadfc14e.png"></div>
</div>
<div class="image-caption">add service</div>
</div>
<p>自动同步需要用到packagist的Api token,查看token</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1236" data-height="485"><img src="https://upload-images.jianshu.io/upload_images/1864602-f042ab12deb1906c.png"></div>
</div>
<div class="image-caption">show profile</div>
</div>
<p>提交配置</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="734" data-height="406"><img src="https://upload-images.jianshu.io/upload_images/1864602-7943c29ce7308e13.png"></div>
</div>
<div class="image-caption">active server</div>
</div>
<h1>结语</h1>
<p>掌握以上的composer基础操作,在日常开发中已经足够使用。如果你是一个没怎么用过composer的php开发者,强烈推荐你从现在开始就用composer。在我看来,composer不仅仅是一个工具,而是联结php应用的生态,如果没有composer或类似的依赖管理工具,很难想象PHP还能保持活力。</p>
</div>
</div>
</div>
<p><br><br></p>
</div>
<div id="MySignature" role="contentinfo">
纵然世间炎凉百态!我自依旧初心不改!!<br><br>
来源:https://www.cnblogs.com/phpk/p/10929836.html
頁:
[1]