Symfony 开发与插件兼容的应用程序的最佳方法。依赖注入?

Symfony 开发与插件兼容的应用程序的最佳方法。依赖注入?,symfony,dependency-injection,event-dispatching,pluggable,Symfony,Dependency Injection,Event Dispatching,Pluggable,我想知道创建与插件完全兼容的应用程序的最佳方法 我习惯于Wordpress插件的概念,您可以定义操作和过滤器,然后在插件中使用。因此,其他人可以在其插件上定义在调用操作或过滤器时执行的方法 我的想法是用一些动作和过滤器创建我的应用程序,然后其他开发者可以构建一个干扰正常应用程序流的包 我正在阅读关于Symfony2依赖注入的文章,但是我没有找到一些全面的例子来做类似的事情 有人有一个真实的例子,类似的东西,我正在寻找? 依赖注入是最好的解决方案还是我应该构建自己的插件处理程序? 编辑: 我所做的

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

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

我的想法是用一些动作和过滤器创建我的应用程序,然后其他开发者可以构建一个干扰正常应用程序流的包

我正在阅读关于Symfony2依赖注入的文章,但是我没有找到一些全面的例子来做类似的事情

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

我所做的是允许其他包将项目添加到我的knp菜单

在我的基本包中:

定义允许订阅方获取和设置菜单数据的筛选器:

# 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'));
    }
}
# 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}
在生成菜单中调度事件:

# 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;
    }
}
将订阅服务器附加到内核事件订阅服务器:

# 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'));
    }
}
# 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/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'));
    }
}
# 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/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'));
    }
}
# 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}

通过这种方式,我可以使用事件调度器的优先级来设置菜单中每组项目的位置。

为您的应用程序提供扩展点(其他开发人员可以在其中钩住他们的自定义行为)的一个很好的起点是使用Symfony中的组件,Symfony是

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

例如,您可以挂接到kernel.request事件并在请求无效时立即返回响应,或者挂接到kernel.Response事件并更改响应内容

请参阅完整的列表

通过使用这些组件,您可以创建一个比Wordpress平台更强大、更可测试、更健壮的插件系统

当然,您可以轻松创建和发送适合您业务逻辑的事件,例如为博客应用程序创建post.created或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}

您好,我会更仔细地查看依赖项容器中的标记服务,谢谢Julien,但我认为下面的答案所说的EventDispatcher正是我所寻找的。。