winkelco / laravel-extension
Laravel 插件、扩展和模块系统
Requires
- php: ^7.0|^8.0
- illuminate/support: ^7|^8|^9
Requires (Dev)
- phpunit/phpunit: ^8.0|^9.0
README
Laravel 插件、扩展和模块系统。灵感来源于 WordPress 插件。
目录
安装
使用 Composer 安装
composer require winkelco/laravel-extension
我们使用自动发现制作了这个包,但您也可以手动添加
# service provider :
WinkelCo\LaravelExtension\LaravelExtensionServiceProvider::class
# aliases
"Extension" => WinkelCo\LaravelExtension\Facades\Extension::class,
"Hook" => WinkelCo\LaravelExtension\Facades\Hook::class
发布配置
php artisan vendor:publish --provider="WinkelCo\LaravelExtension\LaravelExtensionServiceProvider"
已将命名空间添加到您的 Composer 中:(编辑您的 Laravel composer.json
)
"autoload": {
"psr-4": {
"App\\": "app/",
"Extension\\": "app/Extension/",
},
},
然后,您可以生成 composer 自动加载
composer dump-autoload
在安装后第一次,您必须运行此命令在 app\Extension
中生成扩展文件夹
php artisan extension:init
扩展管理页面
对于简单的扩展管理页面,将此路由添加到您的 routes/web.php
use WinkelCo\LaravelExtension\Facades\Extension;
Extension::routes();
保存后,在浏览器中访问 http://mylaravelproject.test/extension
或 'localhost:8000/extension',最终您会看到这个页面:
扩展文件夹结构
默认情况下,扩展路径在 app/Extension
中,您可以在该文件夹中创建扩展。
. app
├── Console
├── Exceptions
├── Extension
│ ├── ExampleExtension
│ │ └── extension.json
│ │ └── ServiceProvider.php
│ ├── MyExtension
│ │ ├── extension.json
│ │ └── MyExtensionServiceProvider.php
│ └── extension.json
├── Http
├── Providers
├── User.php
Artisan 控制台命令支持
轻松创建新扩展
php artisan extension:new ExampleExtension
更新已安装扩展列表
php artisan extension:update-list
获取已安装扩展列表
php artisan extension:list
启用扩展:(插件必须先添加到列表中)
php artisan extension:enable ExamplePlugin
禁用扩展
php artisan extension:disable ExamplePlugin
检查扩展
php artisan extension:inspect ExamplePlugin
获取钩子列表(所有)
php artisan hook:list
获取特定类型的钩子列表(行为或过滤器)
# only action :
php artisan hook:list --action
# only filter :
php artisan hook:list --filter
创建新扩展
使用 Artisan 命令
您可以使用此命令创建新的扩展
php artisan extension:new ExampleTes
成功后,您可以使用以下命令刷新扩展列表
php artisan extension:update-list
您可以通过以下命令检查更新列表是否成功
php artisan extension:list
要启用您的扩展,请使用
php artisan extension:enable ExampleTes
手动
| 注意:此部分使用印尼语,您可以将其翻译。
扩展的位置必须位于主扩展文件夹中,默认情况下位于 app\Extension
,以下是如何创建扩展的简要说明
- 创建主扩展文件夹,例如
app\Extension\MyPlugin
- 在
app\Extension\MyPlugin\extension.json
中创建您的插件配置文件,内容如下
{
"name": "My Example Plugin",
"description": "describe your extension.",
"version": "1.0.0",
"provider": "MyPluginServiceProvider",
"author": {
"name": "winkelco",
"site": "https://github.com/winkelco"
}
}
- 创建您的扩展服务提供者,在上述工作扩展文件夹中,例如
app\Extension\MyPlugin\MyPluginServiceProvider.php
内容如下
<?php
namespace Extension\MyPlugin;
use WinkelCo\LaravelExtension\Support\ServiceProvider;
class MyPluginServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
//
}
}
- 现在,在 Artisan 中运行此命令以更新
app\Extension\extension.json
中的已安装扩展列表
php artisan extension:update-list
您可以在 app\Extension\extension.json
文件中自动添加它,如果您运行上述命令,该命令将自动更新您在 app\Extension\extension.json
中具有的扩展列表,应该是以下内容:
{
"list": [
"MyPlugin"
],
"active": []
}
- 运行以下命令检查该扩展是否已注册:
php artisan extension:list
- 如果已注册但状态不是
active
,请运行以下命令:
php artisan extension:enable MyPlugin
钩子
行为
使用钩子行为,您可以为多个行为回调创建多行为系统和管理行为。
创建行为
Hook::addAction(string $extension, string $name, \Closure $callback, int $priority = 10)
运行行为
Hook::runAction(string $name)
例如,您可以创建一个名为 "save_post" 的行为钩子,该行为可以执行多个行为回调
use WinkelCo\LaravelExtension\Facades\Hook;
use App\Models\Post;
Hook::addAction('extension_name', 'save_post', function ($title) {
$create = Post::create([ 'title' => $title ]);
}, 15);
Hook::addAction('another_extension', 'save_post', function ($title) {
Log::create("Creating post with title {$title}");
}, 10);
您可以运行
use WinkelCo\LaravelExtension\Facades\Hook;
$title = "Example Post";
Hook::runAction('save_post', $title);
过滤器
过滤器可以使数据可以通过多个闭包进行修改,这对于创建扩展非常有用。创建过滤器
Hook::addFilter(string $extension, string $name, \Closure $callback, int $priority = 10)
应用行为
$result = Hook::applyFilter(string $name, $value, ...$params)
例如,我创建了两个用于修改数据 $title
的函数
use WinkelCo\LaravelExtension\Facades\Hook;
Hook::addFilter('extension_name', 'save_post_params', function ($title) {
return "a {$title}.";
}, 15);
Hook::addFilter('another_extension', 'save_post_params', function ($title) {
return strtolower($title);
}, 10);
$title = "Example Post";
$result = Hook::applyFilter('save_post_params', $title);
// result output : a example post.
菜单构建器
此包包含一个简单的菜单构建器,用于在项目中创建动态菜单,以下是一个示例
这是一个示例
use WinkelCo\LaravelExtension\Facades\Menu;
Menu::add('admin.navbar', 'Dashboard', url('/'));
Menu::add('admin.navbar', 'Extension', url('/extension'));
然后,要将渲染结果转换为字符串形式的HTML,请使用这个。例如,我正在创建 sidebar.blade.php
。
@php
$menu = Menu::render('admin.navbar', function ($title, $url) {
return '<li class="nav-item">
<a class="nav-link" href="'.$url.'">
<i class="nav-icon la la-lg la-dashboard"></i>
'.$title.'
</a>
</li>';
});
@endphp
<div class="sidebar">
<nav class="sidebar-nav">
<ul class="nav">
{!! $menu !!}
</ul>
</nav>
</div>
单元测试
您可以使用以下命令使用phpunit运行测试
composer test
或者:(通过composer安装phpunit)
vendor/bin/phpunit tests/HookActionTest
vendor/bin/phpunit tests/HookFilterTest
vendor/bin/phpunit tests/MenuBuilderTest
示例
在 HTML Blade 中创建动态 CSS 和 JavaScript
例如,使用钩子过滤器创建一个带有动态组件的页面。在 layouts/app.blade.php
中
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Example Page</title>
@applyfilter("html__styless")
<!-- dynamic styles with Hook Filter -->
@applyfilter
</head>
<body class="app aside-menu-fixed sidebar-lg-show">
<div id="app"></div>
@applyfilter("html__scripts")
<!-- dynamic scripts with Hook Filter -->
@applyfilter
</body>
</html>
然后在控制器中
public function index()
{
// system filter
Hook::addFilter("system", "html__styles", function ($old_value) {
return $old_value . '<link href="bootstrap.min.css" rel="stylesheet">';
}, 15);
Hook::addFilter("system", "html__scripts", function ($old_value) {
return $old_value .'<script src="bootstrap.min.js"><script>';
}, 15);
// another extension filter
Hook::addFilter("example_extension", "html__scripts", function ($old_value) {
return '<script src="jquery.min.js"><script>' . $old_value;
}, 15);
return view('layouts.app');
}
然后,最终的HTML结果是
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Example Page</title>
<!-- dynamic styles with Hook Filter -->
<link href="bootstrap.min.css" rel="stylesheet">
</head>
<body class="app aside-menu-fixed sidebar-lg-show">
<div id="app"></div>
<!-- dynamic scripts with Hook Filter -->
<script src="jquery.min.js"><script>
<script src="bootstrap.min.js"><script>
</body>
</html>
许可证
MIT许可(MIT)。请参阅许可文件以获取更多信息。