php私有组件以及创建自己的composer私有组件(packagist+git+composer)
1、私有组件
大多数时候我们使用的都是公开可用的开源组件,但有时候如果公司使用内部开发的PHP组件,而基于许可证和安全方面的问题不能将其开源,就需要使用私有组件。对Composer而言,这是小菜一碟。
Composer可用管理放在需要认证的仓库中的私有PHP组件,执行composer install或composer update命令时,如果组件的仓库需要认证凭据,Composer会提醒你需要输入认证信息,此外,Composer还会询问是否把仓库的认证凭据保存在本地的auth.json文件(和composer.json放在同一级)。下面是auth.json的内容示例:
2、创建组件
现在你应该知道怎么查找和使用PHP组件了,下面我们来讨论如何创建PHP组件。创建PHP组件是把工作成果分享给PHP社区成员的好方式,PHP社区乐于分享和帮助他人,如果你在应用中使用了开源组件,那么投桃报李,创建有创意的新开源组件是回报社区最好的方式。
注:别重新编写已经存在的组件,如果是改进现有组件,可以在拉取请求中把改进发送给原本的组件,否则,PHP生态系统将充斥重复的组件。
命名空间
在设置命名空间之前,先要确定厂商名称和包名,即形如laravel/framework这样,要确保其全局唯一性,在Packagist中不存在。
每个组件都有自己的命名空间,说到这里,人们常常误以为组件的命名空间必须与组件的厂商名和包名一致,其实不然,组件使用的命名空间与组件的厂商名和包名无关,厂商名和包名只是为了让Packagist和Composer识别组件,而组件的命名空间是为了在PHP代码中使用组件。
文件系统结构
PHP组件的文件系统结构基本上是确定的:
- src:这个目录用于存放组件的源代码
- tests:存放组件的测试代码
- composer.json:Composer配置文件,用于描述组件,声明组件依赖以及自动加载配置等
- README.md:这个Markdown文件提供关于组件的相关信息、使用文档说明、软件许可证等
- CONTRIBUTING.md:这个Markdown文件告知别人如何为这个组件做贡献
- LICENSE:纯文本文件,声明组件的软件许可证
- CHANGELOG.md:Markdown文件,列出组件在每个版本中引入的改动
composer.json
PHP组件中必须包含composer.json文件,而且这个文件的内容必须是有效的JSON,Composer会使用这个文件中的信息查找、安装和自动加载PHP组件。composer.json文件还包含组件在Packagist目录中的信息。
我们新建一个组件目录(~/Packages/laravelacademy/urlscanner),然后在urlscanner目录下通过如下命令生成composer.json文件:
composer init
然后在终端会让我们按照提示向导一步步填写composer.json内容:
最后回车,会生成相应的composer.json文件,我们对该文件作如下修改:
我们来仔细研究一下这个文件,看看每个部分究竟是什么意思:
- name:组件的厂商名和包名,也是Packagist中的组件名
- description:简要说明组件
- keywords:描述属性的关键字
- homepage:组件网站URL
- license:PHP组件采用的软件许可证(更多软件许可证参考:http://choosealicense.com/)
- authors:作者信息数组
- support:组件用户获取技术支持的方式
- require:组件自身依赖的组件
- require-dev:开发这个组件所需的依赖
- suggest:建议安装的组件
- autoload:告诉Composer自动加载器如何自动加载这个组件
READEME.md
通常这个是用户最先阅读的文件,对托管在Github和Bitbucket中的组件来说,更是如此。标准的READEME.md文件至少提供以下信息:
- 组件的名称和描述
- 安装说明
- 使用说明
- 测试说明
- 贡献方式
- 支持资源
- 作者信息
- 软件许可证
实现组件
开始之前我们使用如下命令安装依赖:composer install
该命令会把依赖组件安装到vendor目录并生成自动加载器。
现在我们要来实现组件的具体功能了。这一步我们要编写组成PHP组件的类、接口和Trait,编写什么类以及编写多少类完全取决于PHP组件的作用。不过组件中的所有类、接口和Trait都要放到src目录下。
对这个组件来说我只需要创建一个类Scanner,位于子命名空间Url中,这个子命名空间位于composer.json文件中设定的LaravelAcademy/UrlScanner命名空间下,Scanner类保存在src/Url/Scanner.php文件。Scanner类实现的逻辑和上一节的URL扫描器示例应用相同,只不过现在我们要把扫描URL的功能封装在一个PHP类中:
<?php namespace LaravelAcademy\UrlScanner\Url; use GuzzleHttp\Client; class Scanner { protected $urls; protected $httpClient; public function __construct(array $urls){ $this->urls = $urls; $this->httpClient = new Client(); } /** * 获取访问指定URL的HTTP状态码 * * @param $url * @return int */ public function getStatusCodeForUrl($url) { $httpResponse = $this->httpClient->get($url); return $httpResponse->getStatusCode(); } /** * 获取死链 * * @return array */ public function getInvalidUrls() { $invalidUrls = []; foreach ($this->urls as $url) { try { $statusCode = $this->getStatusCodeForUrl($url); } catch (\Exception $e){ $statusCode = 500; } } if($statusCode >= 400){ array_push($invalidUrls,['url' => $url, 'status' => $statusCode]); } return $invalidUrls; } }
我们没有解析并迭代处理一个CSV文件,而是把一个URL数组传递给Scanner类的构造函数,因为我们要尽量让这个扫描URL的类通用。如果直接处理CSV文件就限制了这个组件的用途。我们把获取URL的来源开放给用户,让他们自己从文件、数组亦或是CSV文件中获取。所以回到上面的composer.json,我们在suggest中声明了league/csv组件,只是建议安装,并不是必须安装。
提交到Packagis
我们先将代码提交到GitHub(注意将vendor目录添加到.gitignore)仓库(我的是nonfu/urlscanner):
创建自己的git仓库:https://github.com/hyzgtihub/urlscanner.git
涉及到的git命令如下:
1
git init
2
git remote add origin https://github.com/hyzgtihub/urlscanner.git
3
git add .
4
git commit -m “urlscanner"
5
git pull origin master
6
git push origin master
然后在Packagist中通过GitHub账户登录,通过https://packagist.org/packages/submit提交组件,在输入框中输入刚刚提交的GitHub仓库地址:
check成功后点击submit即可将组件提交到Packagist:
其中红色的警告的意思是需要我们通过GitHub Service Hook去GitHub中创建一个钩子,以后每次更新组件的GitHub仓库时通知Packagist。
3、使用组件
至此,我们已经成功将自己的组件提交到Packagist,现在任何人都可以使用Composer安装这个URL扫描器组件,然后在自己的PHP应用中使用。在终端执行如下命令安装这个组件:
1
composer require yokoohumy/urlscanner dev-master
然后在我们的代码中使用:
vendor('yokoohumy.urlscanner.src.Url.Scanner'); // import('yokoohumy.urlscanner.src.Url.Scanner',VENDOR_PATH,'.php'); // $urls = [ 'http://www.baidu.com', 'http://www.ogjdifj.com', 'http://www.bing.com', 'http://www.jianshu.com', ]; $Scanner = new Scanner($urls); $invalidurls = $Scanner->getInvalidUrls(); var_dump($invalidurls); exit();