在发送到数据库之前更新每个学说查询

Update every doctrine query before it is sent to the database

我们是 运行 一个巨大的平台,具有用于多个前端的单个数据库。现在我们将尝试识别我们的慢速查询并更好地了解我们的流量来自哪个页面。

我想在每个 sql 查询中将页面名称作为注释注入,以便在使用 SHOW FULL PROCESSLIST

查看数据库时能够看到它

最后应该是这样的:/*PAGE NAME*/ SHOW FULL PROCESSLIST

如果我在 sequel 专业版中执行此操作,则似乎会列出评论:

如何使用 listener/subscriber 更新每个学说查询以注入自定义评论?

请检查此Symfony documentation : Doctrine Event Listeners and Subscribers以了解以下代码

以下是我为每次更新所做的,以便更新更新时间:

    <?php

namespace App\EventListener;

use App\Entity\AbstractEntity;
use App\Entity\User;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Events;
use Doctrine\Persistence\Event\LifecycleEventArgs;
use Exception;
use Stringable;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use function is_object;

class DatabaseActivitySubscriber implements EventSubscriber
{
    /**
     * @var TokenStorageInterface
     */
    private TokenStorageInterface $tokenStorage;
    /**
     * @var null|User
     */
    private ?User $user;

    public function __construct(TokenStorageInterface $tokenStorage)
    {
        $this->tokenStorage = $tokenStorage;
        $this->user = null;
    }

    /**
     * @return array|string[]
     */
    public function getSubscribedEvents()
    {
        return [
            Events::prePersist,
            Events::preUpdate,
        ];
    }

    /**
     * Initiate the name of the user creating the object with "LastName FirstName (id)"
     *
     * @param LifecycleEventArgs $args
     * @throws Exception
     */
    public function prePersist(LifecycleEventArgs $args)
    {
        $object = $args->getObject();
        if ($object instanceof AbstractEntity && $this->getUser() instanceof User) {
            $object->setCreateUser($this->getUser()->getLastName() . ' ' . $this->getuser()->getLastName() . ' (' . $this->getuser()->getId() . ')');
            $object->setCreateDate();
        }
    }

    /**
     * @return string|Stringable|UserInterface|null|User
     */
    private function getUser()
    {
        if ($this->user instanceof User){
            return $this->user;
        }
        $token = $this->tokenStorage->getToken();
        if (null === $token) {
            return null;
        }

        if (!is_object($user = $token->getUser())) {
            return null;
        }
        $this->user = $user;
        return $this->user;
    }

    /**
     * @param LifecycleEventArgs $args
     * @throws Exception
     */
    public function preUpdate(LifecycleEventArgs $args)
    {
        $object = $args->getObject();
        if ($object instanceof AbstractEntity && $this->getUser() instanceof User) {
            $object->setUpdateUser($this->getuser()->getLastName() . ' ' . $this->getuser()->getLastName() . ' (' . $this->getuser()->getId() . ')');
            $object->setUpdateDate();
        }
    }
}

并在service.yaml中添加:

    App\EventListener\DatabaseActivitySubscriber:
        tags:
            - { name: 'doctrine.event_subscriber' }

Doctrine DBAL 允许您定义自己的连接 class。

doctrine:
    dbal:
        wrapper_class: App\DBAL\MyConnectionWrapper

您可以实现 Doctrine\DBAL\Connection 的子 class 并根据需要覆盖 executeQuery()

class MyConnectionWrapper extends Connection
{
  public function executeQuery($sql, array $params = [], $types = [], ?QueryCacheProfile $qcp = null)
  {
    $sql = '/*PAGE NAME*/ '.$sql;
    return parent::executeQuery($sql, $params, $types, $qcp);
  }
}