droath/plugin-manager 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

droath/plugin-manager

Composer 安装命令:

composer require droath/plugin-manager

包简介

A lightweight PHP package for defining, discovering and instantiating pluggable services.

README 文档

README

A lightweight PHP toolkit for discovering, describing, and instantiating pluggable services. It couples attribute-based metadata with a flexible discovery pipeline so you can publish extensions without wiring every class manually.

Features

  • Attribute-first definitions: describe plugins with #[PluginMetadata] directly on the class.
  • Namespace discovery: scan one or more namespaces for implementations that match your interface contract.
  • Extensible managers: override the constructor of DefaultPluginManager to inject discovery and container wiring.
  • Container integration: opt into PSR-11 containers for dependency-rich plugins.
  • Testing utilities: reference stubbed discovery helpers to keep specs fast and focused.

Installation

composer require droath/plugin-manager

The library targets PHP 8.1+ and expects Composer’s autoloader at runtime.

Core Concepts

  • Plugin metadata attribute: Droath\PluginManager\Attributes\PluginMetadata marks eligible classes and captures identity fields such as id and label.
  • Plugin contracts: every plugin must implement Droath\PluginManager\Contracts\PluginInterface. The Plugin\PluginBase abstract class ships with sensible defaults.
  • Discovery: Discovery\NamespacePluginDiscovery scans configured namespaces for attributed classes that implement one or more target interfaces.
  • Plugin manager: DefaultPluginManager expects a discovery implementation via its constructor. Extend it and override __construct() to provide the discovery strategy (and optionally register a container).
  • Container awareness: when a plugin implements PluginContainerInjectionInterface the manager must satisfy PluginManagerContainerAwareInterface (see Concerns\ContainerAware).

Quick Start

1. Declare a plugin

<?php

namespace App\Acme\Plugin;

use Droath\PluginManager\Attributes\PluginMetadata;
use Droath\PluginManager\Plugin\PluginBase;

#[PluginMetadata(id: 'hello_world', label: 'Hello World')]
final class HelloWorldPlugin extends PluginBase
{
    public function greet(): string
    {
        $name = $this->getConfiguration()['name'] ?? 'World';

        return sprintf('Hello %s!', $name);
    }
}

2. Create a manager by overriding __construct()

<?php

namespace App\Acme\Plugin;

use Droath\PluginManager\Attributes\PluginMetadata;
use Droath\PluginManager\Concerns\ContainerAware;
use Droath\PluginManager\Contracts\PluginInterface;
use Droath\PluginManager\Contracts\PluginManagerContainerAwareInterface;
use Droath\PluginManager\Contracts\PluginDiscoveryInterface;
use Droath\PluginManager\DefaultPluginManager;
use Droath\PluginManager\Discovery\NamespacePluginDiscovery;
use Illuminate\Container\Container; // Replace with your PSR-11 container implementation

final class HelloPluginManager extends DefaultPluginManager implements PluginManagerContainerAwareInterface
{
    use ContainerAware;

    public function __construct(?PluginDiscoveryInterface $discovery = null)
    {
        $this->setContainer(Container::getInstance());

        parent::__construct($discovery ?? new NamespacePluginDiscovery(
            namespaces: ['App\Acme\Plugin'],
            pluginInterface: PluginInterface::class,
            pluginMetadataAttribute: PluginMetadata::class,
        ));
    }
}

Overriding the constructor lets you keep one canonical discovery definition while still injecting alternative discovery implementations (e.g., stubs) for tests.

3. Instantiate plugins

$manager = new HelloPluginManager();

$plugin = $manager->createInstance('hello_world', [
    'name' => 'Developers',
]);

echo $plugin->greet(); // "Hello Developers!"

createInstance() fetches the definition from cached discovery results, merges any runtime configuration, and returns a fully constructed plugin object.

Container-Aware Plugins

When a plugin needs services from your PSR-11 container, implement PluginContainerInjectionInterface and let the manager supply the container.

<?php

namespace App\Acme\Plugin;

use Droath\PluginManager\Contracts\PluginContainerInjectionInterface;
use Droath\PluginManager\Plugin\PluginBase;
use Psr\Container\ContainerInterface;

final class ContainerBackedPlugin extends PluginBase implements PluginContainerInjectionInterface
{
    public function __construct(
        array $configuration,
        array $pluginDefinition,
    ) {
        parent::__construct($configuration, $pluginDefinition);
    }

    public static function create(
        ContainerInterface $container,
        array $configuration,
        array $pluginDefinition,
    ): static {
        return new static($configuration, $pluginDefinition, $container->get('service_id');
    }
}

Because HelloPluginManager implements PluginManagerContainerAwareInterface and calls setContainer() in its constructor, container-aware plugins receive the PSR-11 container automatically. If a plugin requests a container but the manager is not container-aware, PluginManagerRuntimeException is thrown.

Definition Caching

DefaultPluginManager caches discovery results within the lifecycle of the manager. Use these helpers when definitions change at runtime:

  • disableCache() — bypass the cache on the next lookup (useful when discovery inputs change).
  • resetCache() — clear the cache while keeping caching enabled (helps after deployments or configuration changes).

Both methods return the manager instance for fluent chaining.

Testing Helpers

Leverage an in-memory discovery implementation during testing so you can bypass namespace scans:

use Droath\PluginManager\Contracts\PluginDiscoveryInterface;
use Droath\PluginManager\Discovery\PluginMetadata;
use Droath\PluginManager\Tests\Stubs\ArrayDiscovery;
use App\Acme\Plugin\HelloPluginManager;
use App\Acme\Plugin\HelloWorldPlugin;

$discovery = new ArrayDiscovery([
    PluginMetadata::make(HelloWorldPlugin::class, [
        'id' => 'hello_world',
        'label' => 'Hello World Plugin',
    ]),
]);

$manager = new HelloPluginManager($discovery);

The repository’s specs under tests/Unit show additional examples covering discovery filters, caching, and container-aware plugins.

Development

  • Static analysis: composer analyze
  • Run the test suite: composer test
  • Check coding standards: vendor/bin/phpcs --standard=phpcs.xml src

droath/plugin-manager 适用场景与选型建议

droath/plugin-manager 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 1.05k 次下载、GitHub Stars 达 0, 最近一次更新时间为 2025 年 02 月 26 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 droath/plugin-manager 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 droath/plugin-manager 我们能提供哪些服务?
定制开发 / 二次开发

基于 droath/plugin-manager 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 1.05k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 9
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-02-26