手把手教你创建、测试、版本管理、发布和维护自己的 Laravel 扩展包。
Laravel 生态之所以繁荣,离不开开源社区的贡献。你每天用的 Spatie、Laravel Debugbar、Livewire,本质上都是开发者分享出来的扩展包。
如果你写过一些能在多个项目里复用的功能——自定义验证规则、辅助函数、UI 组件之类的——那恭喜,你其实已经有了做扩展包的基础。
这篇文章会带你走完整个流程:从搭建项目结构,到编写测试、配置 CI/CD,最后发布到 Packagist。
还不是会员?点击这里阅读完整文章!
先从最基础的开始。
我们要做一个叫 mycompany/laravel-awesome 的扩展包,功能很简单:提供一个 @shout() 的 Blade 指令。
在 Laravel 项目里(或者单独建个目录),执行:
mkdir -p packages/mycompany/laravel-awesome
cd packages/mycompany/laravel-awesomecomposer init最简单的扩展包结构长这样:
laravel-awesome/
├── composer.json.json
├── src/
│ ├── LaravelAwesomeServiceProvider.php
│ └── Helpers/
│ └── shout.php
└── tests/
└── ExampleTest.php在扩展包里新建文件:
src/Helpers/shout.php
<?php
if (! function_exists('shout')) {
/**
* 将给定字符串转换为大写。
*
* @param string $text
* @return string
*/
function shout(string $text): string
{
return strtoupper($text);
}
}再创建一个服务提供者文件:
src/LaravelAwesomeServiceProvider.php:
<?php
namespace MyCompany\LaravelAwesome;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Blade;
class LaravelAwesomeServiceProvider extends ServiceProvider
{
public function boot()
{
// 注册 Blade 指令
Blade::directive('shout', function ($expression) {
return "<?php echo strtoupper($expression); ?>";
});
// 加载辅助函数文件
$this->loadHelpers();
}
public function register()
{
//
}
protected function loadHelpers(): void
{
foreach (glob(__DIR__ . '/Helpers/*.php') as $filename) {
require_once $filename;
}
}
}在 composer.json 里告诉 Laravel 去哪找这个类:
"autoload": {
"psr-4": {
"MyCompany\\LaravelAwesome\\": "src/"
}
},
"extra": {
"laravel": {
"providers": [
"MyCompany\\LaravelAwesome\\LaravelAwesomeServiceProvider"
]
}
}最后刷新一下自动加载:
composer dump-autoload在 Laravel 项目里试试:
@shout('hello world')输出 → HELLO WORLD
完成!你的第一个 Laravel 扩展包就这么跑起来了。
这里用 Pest,语法比 PHPUnit 简洁不少。
先装 Pest:
composer require pestphp/pest --dev创建 tests/ExampleTest.php:
<?php
it('将文本转换为大写', function () {
$result = strtoupper('laravel');
expect($result)->toBe('LARAVEL');
});运行测试:
vendor/bin/pest把测试放在扩展包目录里,这样即使 Laravel 升级了,你也能及时发现兼容性问题。
发布之前,先在另一个 Laravel 项目里测一下。
在主项目的 composer.json 里加上:
"repositories": [
{
"type": "path",
"url": "packages/mycompany/laravel-awesome"
}
],然后安装:
composer require mycompany/laravel-awesome:*这样就能快速迭代,不用每次都推到 GitHub。
用 GitHub Actions 自动跑测试。新建 .github/workflows/tests.yml:
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
- run: composer install --prefer-dist --no-progress
- run: vendor/bin/pest这样每次 push 代码,测试就会自动跑一遍。
扩展包的版本管理很重要,要遵循语义化版本(SemVer)规范。
发布时这么操作:
git add .
git commit -m "Initial release"
git tag v1.0.0
git push origin main --tags打上 tag 后,CI 会自动跑,Composer 也能根据 tag 管理版本。
现在别人就能装你的扩展包了:
composer require mycompany/laravel-awesome扩展包发布后,还要持续维护:
如果你有多个扩展包(比如一套 UI 组件),可以用 monorepo 的方式统一管理,配合 laravel/pint 和 phpstan 这些工具共享配置。
这样做的好处是代码风格统一,依赖更新也方便。
再加个工作流 .github/workflows/release.yml:
name: Auto Release
on:
push:
tags:
- 'v*.*.*'
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ncipollo/release-action@v1
with:
generateReleaseNotes: true这样每次打 tag,GitHub 就会自动生成 release 页面,Packagist 也会同步。
到这里,你已经走完了从想法到发布的全流程:搭建结构 → 编写代码 → 测试 → CI/CD → Packagist 发布。
做扩展包不只是分享代码那么简单,它让你深入了解开源项目的运作机制,学会如何维护一个公开的项目,也能为 Laravel 生态做出贡献。
一旦掌握了这套流程,你会发现自己写的代码越来越模块化、越来越好复用,而且能帮助到更多开发者。
题外话:最近花了很久的时间零零散散的将 Laravel Livewire4 的文档翻译成了中文,如果对 Laravel Livewire 感兴趣,可以查看文档 Laravel Livewire4 中文文档