winkelco/laravel-extension

Laravel 插件、扩展和模块系统

2.3.3 2022-04-26 18:46 UTC

This package is auto-updated.

Last update: 2024-09-27 00:40:57 UTC


README

Laravel 插件、扩展和模块系统。灵感来源于 WordPress 插件。

screenshot preview

目录

安装

使用 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)。请参阅许可文件以获取更多信息。