1

我想知道创建与插件完全兼容的应用程序的最佳方法。

我习惯了 Wordpress 插件概念,您可以定义操作和过滤器,然后在您的插件中使用。所以其他人可以在他们的插件上定义在调用动作(或过滤器)时执行的方法。

我的想法是使用一些操作和过滤器创建我的应用程序,然后其他开发人员可以构建一个干扰“正常”应用程序流程的 Bundle...

我正在阅读有关 Symfony2 依赖注入的信息,但我没有找到一些全面的示例来执行我​​想要的类似操作。

  • 有人有一个我正在寻找的类似东西的真实例子吗?
  • 依赖注入是最好的解决方案还是我应该构建自己的插件处理程序?

编辑:

我做了什么来允许其他包将项目添加到我的 knp-menu 菜单中。

在我的基础包中:

定义允许订阅者获取和设置菜单数据的过滤器:

# BaseBundle/Event/FilterMenuEvent.php

class FilterMenuEvent extends Event
{
    protected $menu;

    public function __construct($menu)
    {
        $this->menu = $menu;
    }

    public function getMenu()
    {
        return $this->menu;
    }
}

定义菜单事件:

# Event/MenuEvents.php
final class MenuEvents
{
    const BEFORE_ITEMS = 'menu.before.items';
    const AFTER_ITEMS = 'menu.after.items';
}

设置订阅者:

# Event/MenuSubscriber.php
class MenuSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array(
            'menu.after.items'     => array(
                array('homeItems', 9000),
                array('quickactionsItems', 80),
                array('adminItems', 70),
             ...
                array('logoutItems', -9000),
            )
        );
    }
    public function homeItems(FilterMenuEvent $menu_filter)
    {
        $menu = $menu_filter->getMenu();
        $menu->addChild('Home', array('route' => 'zashost_zaspanel_homepage'));
    }

    public function quickactionsItems(FilterMenuEvent $menu_filter)
    {
        $menu = $menu_filter->getMenu();
        $menu->addChild('Quick actions', array( 'route' => null));
        $menu['Quick actions']->addChild('Add hosting', array( 'route' => 'zashost_zaspanel_register_host'));
    }
}

菜单生成中的调度事件:

# Menu\Builder.php

class Builder extends ContainerAware
{
    public function userMenu(FactoryInterface $factory, array $options)
    {
        $menu = $factory->createItem('root');

        $this->container->get('event_dispatcher')->dispatch(MenuEvents::AFTER_ITEMS , new FilterMenuEvent($menu));

        return $menu;
    }
}

将订阅者附加到内核事件订阅者:

# services.yml
    services:
        # Menu items added with event listener
        base_menu_subscriber:
            class: Acme\BaseBundle\Event\MenuSubscriber
            arguments: ['@event_dispatcher']
            tags:
                - {name: kernel.event_subscriber}

然后在第三方捆绑包中:

设置我的第三方事件订阅者:

class MenuSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array(
            'menu.after.items'     => array('afterItems', 55)
        );
    }

    public function afterItems(FilterMenuEvent $menu_filter)
    {
        $menu = $menu_filter->getMenu();
        $menu->addChild('Backups', array( 'route' => null));
        $menu['Backups']->addChild('Create new backup', array( 'route' => null));
        return $menu;
    }
}

并附加到内核事件订阅者:

# srevices.yml
services:
    menu_subscriber:
        class: Acme\ThirdPartyBundle\Event\MenuSubscriber
        arguments: ['@event_dispatcher']
        tags:
            - {name: kernel.event_subscriber}

这样我就可以使用 Event Dispatcher 的优先级来设置菜单中每组项目的位置。

4

1 回答 1

0

为您的应用程序提供扩展点的一个很好的起点是使用Symfony的EventDispatcher组件(观察者模式的实现),其他开发人员可以在其中挂钩他们的自定义行为。

Symfony 已经在它自己的核心(HttpKernel)中广泛使用了该组件,以允许其他组件(或插件,如果你愿意的话)挂钩 http 请求 -> 响应流中的各个点,并处理从请求匹配到响应生成的所有事情。

例如,kernel.request如果请求无效,您可以连接到事件并立即返回响应,或者连接到kernel.response事件并更改响应内容。

查看默认 KernelEvents的完整列表。

通过仅使用这些(还有许多与其他组件相关的其他组件),您可以创建一个比 Wordpress“平台”更强大、更可测试和更健壮的插件系统。

当然,您可以轻松地为博客应用程序创建和分发适合您的业务逻辑的自己的事件(例如创建类似post.createdor的事件comment.created)。

现在,为了一个例子,这里是你将如何配置一个“插件”,它将对生成的响应做一些事情,然后将触发另一个事件(可以被另一个插件使用)

namespace Vendor;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;

class ResponseAlter implements EventSubscriberInterface
{

    private $dispatcher;

    public function __construct(EventDispatcher $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }

    public function doSomethingWithResponse(FilterResponseEvent $event)
    {
        $response = $event->getResponse();

        /**
         * let other plugins hook to the provide.footer event and
         * add the result to the response
         */
        $footer = new ProvideFooterEvent();
        $this->dispatcher->dispatch('provide.footer', $footer);

        $this->addFooterProvidedByPluginToResponse($response, $footer->getProvidedFooter());

        $event->setResponse($response);
    }

    static function getSubscribedEvents() 
    {
        return array(
            'kernel.response' => 'doSomethingWithResponse'
        );
    }
}

现在您只需将您的服务标记为服务订阅者即可。您刚刚插入了 HttpKernel 组件:

services:
    my_subscriber:
        class: Vendor\ResponseAlter
        arguments: ['@event_dispatcher']
        tags:
            - {name: kernel.event_subscriber}
于 2013-01-31T21:58:54.117 回答