如何在项目中自动加载自有的 PHP 扩展包?
俗话说万事开头难,如果你之前没有发布过 php 扩展, 并且不知道怎么开始编写一个 php 扩展,你可能会有很多疑问,比如:php 扩展实际安装在了哪里?现在已知扩展安装在了 vendor/
目录下,但是该目录已经被 ignored 记录,并被 git 忽略,为什么这样做…
现在你有三个选项可以参考
下面是三种 php 扩展开发方式:
- 在 GitHub 创建一个新的仓库(repo), 并将其关联 Packagist
相对复杂,这会在 Packagist 创建一个不完整的扩展包 - 创建一个新的文件夹,并将扩展更新指向该目录。
相对简单,但是需要你在部署服务器时执行特定配置 - 将扩展集成在项目代码中,直到可以发布
最简单,这正是我们今天要讨论的
事例场景
我的朋友告诉我他发布了 Laravel Socialite 扩展,用于向 Laravel 应用添加社交身份验证。
因此,今天我们将以此为例,一步步创建一个可以发布的 php 扩展。
确定命名空间
首先,我们要确定我们的命名空间,Socialite 规定了我们实现 Socialite 社交身份验证组件的接口(interface),并没有规定命名空间的设定,我们必须继承并实现 Socialite 接口,因此我们想一下我们要发布的 Socialite 自定义组件实现了什么并选择一个合适的命名空间。
我首先想到的是这是一个基于 Socialite 的扩展,发布在 mattstauffer/socialite-providers
,所以我的命名空间会是: Mattstauffer/SocialiteProviders
.
我将会创建 MaceBookProvider
类,用于 MaceBook.com
的登录身份验证,一个社交平台。
建立档案
现在建立一个新的文档:
<?php
namespace Mattstauffer\SocialiteProviders;
use Laravel\Socialite\Two\AbstractProvider;
use Laravel\Socialite\Two\ProviderInterface;
class MaceBookProvider extends AbstractProvider implements ProviderInterface
{
// ...
}
但是我们要把它放在那?
在你的文件夹中建立一个 src/
并把你的代码放在里面,这是选择一。
如果你并不想放在 src/
目录下, 因为你已经计划好怎么处理他,你也可以创建一个像 packages/
这样的文件夹。 下文中,我们将假设您以 packages/
为代码目录来处理。
现在我们把 packages/
文件夹作为我们扩展的顶级文件夹, Mattstauffer
作为主要命名空间。 因此, 我们需要添加一个 SocialiteProviders
文件夹,并创建packages/SocialiteProviders/MaceBookProvider.php
文件。
添加 Autoload
现在我们要做的的是告诉 Composer 当我们的应用需求 Mattstauffer/
命名空间下的类时,可以在 packages/
找到相应的类。那么该如何实现这个呢?
幸运的是 PSR-4 正式为此而生的!所以我们只要告诉 Composer 我们的 packages/
遵循 PSR-4 规则即可,Composer 会帮我们加载该目录下的所有类。
笔记:你可以将,命名空间
packages/SocialiteProviders
修改为Mattstauffer/SocialiteProviders
以帮助 Composer 能够更精准的发现您的类。
现在,编辑您的 composer.json
修改 autoload
字段,如果你用的是比较先进的框架(像 Laravel),您可能已经发现了该文件。
"autoload": {
"psr-4": {
"App\\": "app/"
},
现在添加我们的扩展指向:
"autoload": {
"psr-4": {
"App\\": "app/",
"Mattstauffer\\": "packages/"
},
执行 composer dump-autoload
以重载 autoload。
至此,一个你的自定义扩展发布完成,你可以到此为止,当然如果你想要了解更多,请继续。
当我们的扩展需要其他扩展的支持我们要怎么办?(依赖管理)
如果您的目的是发布该扩展,那么现在还差很多,例如,您可能在开发该扩展时使用了其他扩展(避免重复造轮子是很有必要的),所以,你要管理的不仅仅是框架的 composer.json
,你还需要自己的 composer.json
。
如果是上述情况,您需要建立一个独立于 Git 仓库之外的文件件。 (免费视频地址 here)
拿 BestPackage
作为例子,假如您的项目文件夹为:BestProject
,他的目录结构将会像下面这样:
\Users
\mattstauffer
\Sites
\BestPackage
\BestProject
那么现在该如何使用 Git 仓库之外的文件夹目录呢?
这需要你修改框架 composer.json
只要将 (../BestPackage
) 以 path 的方式配置即可,具体配置会在下面给出。
准备发布您的扩展
首先,确保您的扩展包含有效的 composer.json
文件。你可以通过在扩展目录下运行 composer init
以初始化该文件。
通过提示文件,选择相应的选项,初始化您的 composer.json
。
现在我们的 “BestPackage” 扩展的 composer.json
初始化完成,它可能像下面这样:
{
"name": "mattstauffer/best-package",
"description": "The best package!",
"type": "library",
"require-dev": {
"tightenco/tlint": "^4.0"
},
"license": "MIT",
"authors": [
{
"name": "Matt Stauffer",
"email": "matt@tighten.co"
}
],
"require": {}
}
通过 Path 类型加载扩展
接下来,回到框架目录,编辑框架下的 composer.json
,创建一个 repositories
字段,告诉 composer 以 path 的方式加载您的扩展:
{
// require, require-dev, etc.
"repositories": [
{
"type": "path",
"url": "../BestPackage"
}
]
}
应用中扩展的使用
最终,你可以像下面这样加载您的扩展了
composer require mattstauffer/best-package
提醒
这种方法的缺陷是:不能随您的代码仓库一起部署,还需要额外的配置以告诉 Compose 去哪里拉取。
但是,这比较有利于最终软件的发布。
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。