noccylabs/pluggable

应用程序的插件管理器

0.2.4.3 2014-08-05 11:56 UTC

This package is auto-updated.

Last update: 2024-09-07 07:09:12 UTC


README

注意:此README适用于Pluggable的0.2.x分支

Pluggable是一个PHP插件管理器。它提供了一个裸露的可控框架,可以从文件系统或甚至从.zip或.phar文件按需加载和卸载代码占位符。

安装

$ composer require noccylabs/pluggable:0.2.x-dev

使用

创建一个NoccyLabs\Pluggable\Manager\PluginManager实例,并添加您希望从中加载插件的后端

    // Find and load all plugins from virtual filesystem $vfs
    $plug = new PluginManager();
    $plug
        ->addBackend(new VirtFsBackend($vfs, null))
        ->findPlugins(true)
        ;

后端

您可以添加多个后端。它们的添加顺序是相关的,如果插件在多个位置找到。例如,想象以下场景:

  • 插件plugin.foofooapp.phar一起提供,并使用StaticBackend加载。
  • 文件~/.fooapp/plugins/plugin.foo.zip也包含plugin.foo,并通过VirtFsBackend加载。

当加载插件plugin.foo时,它将从VirtFs后端加载,因为它是在最后遇到的。这允许您包含可以外部升级的静态插件。

    $plug
        ->addBackend(new StaticBackend(..))
        ->addBackend(new VirtFsBackend(..))

DirectoryBackend

Directorybackend从一组目录加载插件。此后端只能直接从源加载,而不能通过phar、zip或其他存档。

    new DirectoryBackend(array(
        "/foo/bar",
        "/foo/biz",
        "/var/bar"
    ));

VirtFsBackend

VirtFsBackend从由映射目录和zip文件组成的VirtFs文件系统加载插件。要使VirtFs后端工作,必须将协议分配给VirtFs对象(默认名称"plugins"),以允许通过virtfs包装器访问插件。

    new VirtFsBackend($vfs, "/");

StaticBackend

StaticBackend返回静态预初始化插件的列表。对于嵌入插件,例如在创建phar可执行文件时使用。

    new StaticBackend(array(
        "my.plugin.id.one" => 'My\Plugin\Class',
        "my.plugin.id.two" => 'My\Other\Plugin\Class'
    ));

查找插件

true传递给PluginManager#findPlugins()将加载后端找到的所有插件

    $plug->findPlugins(true);

上面的功能与以下相同

    $plug->findPlugins( function ($plugin) {
        return true;
    });

要选择要加载的插件,可以这样做

    // Read plugins loaded since last time
    $plugins_to_load = file("plugins.lst", FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
    
    // Use a custom callback to see if the plugin is in the list
    $plug->findPlugins( function ($plugin) use ($plugins_to_load) {
        $plugin_id = $plugin->getPluginId();
        return in_array($plugin_id, $plugins_to_load);
    });
    
    // Write the list back out
    $loaded_plugins = $plug->getLoadedPluginIds();
    file_put_contents("plugins.lst", join("\n", $loaded_plugins));

编写插件

插件应实现NoccyLabs\Pluggable\Plugin\PluginInterface或扩展NoccyLabs\Pluggable\Plugin\Plugin。如果您选择使用接口,您有责任响应PluginInterface#onActivate()以及PluginInterface#isActivated()以反映状态。如果您扩展插件,您可以代替覆盖Plugin#load()方法,将齿轮和扳手留给Pluggable。

插件需要在支持的任何语言中具有清单(除非使用StaticBackend加载),例如json、yaml或sdl。请注意,yaml和sdl可能需要安装额外的库才能进行解析。

| Language  | Filename                 | Requirements                |
|===========|==========================|=============================|
| Json      | `plugin.json`            | php5-json                   |
| Yaml      | `plugin.yml`             | php5-yaml or symfony/yaml   |
| Ini       | `plugin.ini`             |                             |

文件应定义以下值

  • id - 插件id,例如foovendor.myplugin
  • ns - 插件根目录的命名空间(psr-4)
  • class - 从指定ns加载的类
  • name - 插件名称

接口

通过调用PluginManager#addInterfaceLoader(),可以为实现特定接口或扩展特定类的插件创建回调。内部使用instanceof来比较实例与请求的名称。

    class MyPlugin extends Plugin implements ICanAddInterface
    { ... }

    $plug->addInterfaceLoader("ICanAddInterface", function ($plugin) {
        $sum = $plugin->addNumbers(5, 4);
    });

或用于设置容器等

    $plug->addInterfaceLoader($container_interface, function ($plugin) use ($container) {
        $plugin->setContainer($container);
    });

通用加载器

还提供了通用加载器

    $plug->addLoader(function ($plugin) {
        // ...
    });