SonataAdminBundle使用事件订阅者

时间:2012-10-16 19:41:13

标签: symfony symfony-2.1 sonata-admin

我尝试在SonataAdminBundle表单中设置当前经过身份验证的用户:

protected function configureFormFields(FormMapper $formMapper)
{
    $formMapper
    ->add('title')
    ->add('content')
    ->add('slug')
    //->add('user')
    ;
}

由于我不希望用户选择/选择自己的用户,我想我想在用户发送表单的过程中设置用户名(没有任何用户)用户对象)。 (注意:我想以几种形式使用它,所以我需要一个通用的解决方案。)

我现在所做的是在我读完这篇文章之后设置一个EventListener:http://symfony.com/doc/current/cookbook/service_container/event_listener.html

class PostListener
{
    protected $container;

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


    public function prePersist(LifeCycleEventArgs $args)
    {
        $entity = $args->getEntity();

        //Get user
        $securityContext = $this->container->get('security.context');
        $user = $securityContext->getToken()->getUser();

        //Set authenticated user as autor
        $entity->setUser($user);
    }
}

包括服务:

post.listener:
  class: Backender\BlogBundle\Listener\PostListener
  calls:
    - [ setContainer, [ @service_container ] ]
  tags:
    - { name: doctrine.event_listener, event: prePersist }

现在不确定,如果这是正确的方法,因为我不想指定我想要设置用户的表单。 (这个人想要在每个表格上设置用户吗?)

通过更多研究,似乎我可以像这样使用事件订阅者:http://symfony.com/doc/2.0/cookbook/form/dynamic_form_generation.html 在这个例子中,他们使用FormEvents :: PRE_SET_DATA,我想在我的情况下我必须使用POST_SET_DATA。

我在这里遇到了一些问题!:

1:我对SonataAdminBundle很陌生,在那里我们使用受保护的函数configureFormFields(FormMapper $ formMapper)...其中->addEventSubscriber()不可用?

2:这是正确的方法吗?我真的没有找到像sonata-admin那样的例子。

我感谢你的每一个帮助! 最好的问候......

3 个答案:

答案 0 :(得分:5)

尝试使用$formMapper->getFormBuilder()->addEventSubscriber($subscriber);

答案 1 :(得分:1)

最后,我找到了两个可能解决我问题的方法。我想在这里描述这些可能性,因为找不到那么多东西。

查询实例的事件侦听器 呼叫服务:

   blog.post.listener:
      class: Acme\BlogBundle\Listener\PostListener
      arguments: ['@service_container']
      tags: 
        - { name: doctrine.event_listener, event: prePersist }

听众类:

class PostListener
{
    protected $container;

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


    public function prePersist(LifeCycleEventArgs $args)
    {
        $entity = $args->getEntity();

        //Get user
        $securityContext = $this->container->get('security.context');
        $user = $securityContext->getToken()->getUser();

        if ($entity instanceof Post) {

            //Set authenticated user as autor
            $entity->setUser($user);

        }
    }
}

第二种方式(也许更容易)是在SonataAdminBundle的管理类中使用prePersist

作为服务调用(使用服务容器或安全上下文作为参数):

blog.admin.post:
  class: Acme\BlogBundle\Admin\PostAdmin
  tags:
    - { name: sonata.admin, manager_type: orm, group: Article Handling, label: Posts }
  arguments: [null, Acme\BlogBundle\Entity\Post, SonataAdminBundle:CRUD, @service_container]

PostAdmin: (注意,我使用容器,因为我将来需要更多东西)

class PostAdmin extends Admin
{
    protected $securityContext;

    public function __construct($code, $class, $baseControllerName, ContainerInterface $container)
    {
        parent::__construct($code, $class, $baseControllerName);
        $this->container = $container;
    }

    protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper
        ->add('title')
        ->add('content')
        ;

    }


    public function prePersist($post)
    {
        $user = $this->container->get('security.context')->getToken()->getUser();
        $post->setUser($user);
    }

}

答案 2 :(得分:0)

我通过注入Event Dispatcher解决了向Admin Class添加事件的问题:

    <service id="acme.listener.contract"
             class="Acme\AppBundle\Event\ContractListener">
         <argument type="service" id="twig"></argument>   
         <argument type="service" id="mailer"></argument>   
        <tag name="kernel.event_listener" event="contract.created" method="onContractCreated" />
    </service>

然后在我的管理类中,我将事件添加到现有方法中:

use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Core\SecurityContextInterface;

class ContractAdmin extends Admin
{
    protected $dispatcher;

/**
 * Security Context
 * @var \Symfony\Component\Security\Core\SecurityContextInterface
 */
protected $securityContext;

public function setEventDispatcher(EventDispatcherInterface $dispatcher)
{
    $this->dispatcher = $dispatcher;
}

public function setSecurityContext(SecurityContextInterface $securityContext)
{
    $this->securityContext = $securityContext;
}

public function prePersist($contract)
{
    $user = $this->securityContext->getToken()->getUser();
    $contract->setUser($user);

    $event = new ContractEvent($contract);

    $dispatcher = $this->dispatcher;
    $dispatcher->dispatch(
        ContractEvents::CONTRACT_CREATED,
        $event
    );
}

这允许我在其他地方添加我在我的应用程序中共享的额外事件。

在您的情况下,您只需注入安全上下文:

    sonata.admin.contract:
    class: Acme\AppBundle\Admin\ContractAdmin
    tags:
        - { name: sonata.admin, manager_type: orm, group: "Contracts", label_catalogue: "messages", label: "Auftragsübersicht" }
    arguments:
        - ~
        - Acme\AppBundle\Entity\Contract
        - ~         
    calls:
        - [ setSecurityContext, [@security.context]]
        - [ setEventDispatcher, [@event_dispatcher]]