学说坚持后的Symfony独白

时间:2014-09-24 14:02:38

标签: symfony doctrine-orm

我需要使用monolog记录所有用户操作。但只有当操作持久化数据时才能使用教义,插入,更新或删除。

我该怎么办?我可以定义一个通用的方法,比如" afterPersist"记录每一个动作?

Thx!

编辑:

听众:

use Doctrine\ODM\MongoDB\Event\OnFlushEventArgs;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\SecurityContextInterface;

class DatabaseLogger
{
    protected $logger;
    protected $security_context;
    protected $request;

    public function __construct(LoggerInterface $logger, ContainerInterface $service_container)
    {
        $this->logger = $logger;
        $this->setSecurityContext($service_container->get('security.context'));
    }

    public function setRequest(RequestStack $request_stack)
    {
        $this->request = $request_stack->getCurrentRequest();
    }

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

    public function onFlush(OnFlushEventArgs $args)
    {
        // configure this however you want
    }
}

和service.yml

cc.listener.database_logger:
    class: Cc\HitoBundle\Listener\DatabaseLogger
    tags:
        - { name: doctrine_mongodb.odm.event_listener, event: onFlush }
        - { name: monolog.logger, channel: database_access }
    calls:
        - [ setRequest, [@request_stack] ]
    arguments: [ @logger, @service_container ]

添加安全上下文时出错:

  

ServiceCircularReferenceException:检测到服务的循环引用" doctrine_mongodb.odm.default_document_manager",路径:" doctrine_mongodb.odm.default_document_manager - > doctrine_mongodb.odm.default_connection - > doctrine_mongodb.odm.event_manager - > cc.listener.post_persist - > security.context - > security.authentication.manager - > security.user.provider.concrete.user_db"

2 个答案:

答案 0 :(得分:3)

使用以下内容注册听众:

建立一个监听器:

namespace Acme\MyBundle\EventListener;

use Doctrine\ORM\Event\LifecycleEventArgs;

class PersistLogger
{
       public $logger;

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

       public function postPersist(LifecycleEventArgs $args)
       {
           // configure this however you want
           $this->logger->addDebug('whatever');
       }
}

config.yml

中注册听众
acme_mybundle.eventlistener.persistlogger:
    class: Acme\MyBundle\EventListener\PersistLogger
    tags:
        - { name: doctrine.event_listener, event: postPersist }
    argument: [ @logger ]

编辑: 如果要将用户存储在数据库中(例如使用FOSUserBundle),则将安全上下文注入到教义侦听器会导致循环引用异常。这是因为安全上下文需要注入实体管理器,以便它可以从数据库中获取用户,但由于监听器,实体管理器依赖于安全上下文。

解决方法是注入整个服务容器(执行此操作的唯一时间之一是合理的),并从那里获取安全上下文:

namespace Acme\MyBundle\EventListener;

use Psr\Log\LoggerInterface,
    Symfony\Component\DependencyInjection\ContainerInterface,
    Symfony\Component\Security\Core\SecurityContextInterface;

protected $service_container;
protected $logger;

public function __construct(LoggerInterface $logger, ContainerInterface $service_container) 
{
    $this->service_container = $service_container;
    $this->logger = $logger;
}

public function getSecurityContext() 
{
    return $this->service_container->get('security.context');
}

acme_mybundle.eventlistener.persistlogger:
    class: Acme\MyBundle\EventListener\PersistLogger
    tags:
        - { name: doctrine.event_listener, event: postPersist }
    argument: [ @logger, @service_container ]

答案 1 :(得分:1)

我认为你可能会看一下the cookbook,有一个非常好的条目可以谈论Doctrine的事件。

此外,您可以查看method to create custom monolog chanels