#php #mysql #doctrine-orm #doctrine
#php #mysql #doctrine-orm #doctrine
Вопрос:
Мы используем огромную платформу, которая имеет единую базу данных для нескольких интерфейсов. Теперь мы собираемся попытаться определить наши медленные запросы и получить лучшее представление о том, с какой страницы поступает наш трафик.
У меня была идея вводить имя страницы в качестве комментария в каждый sql-запрос, чтобы иметь возможность видеть его при просмотре базы данных с помощью SHOW FULL PROCESSLIST
В конце это должно выглядеть так: /*PAGE NAME*/ SHOW FULL PROCESSLIST
Если я сделаю это в sequel pro, кажется, что комментарий попадает в список, а затем:
Как я могу обновлять каждый запрос doctrine, используя слушателя / подписчика для ввода пользовательского комментария?
Комментарии:
1. Прослушиватель / подписчик / фильтры Doctrine не будут поддерживать это. Все, что я могу предложить, это расширить объект Doctrine connection, а затем, возможно, найти место, прежде чем сгенерированный sql будет отправлен на сервер базы данных. Но я не думаю, что ваш подход является хорошим. На серверах баз данных есть много инструментов, профилирующих инструменты для такого рода вещей.
Ответ №1:
Doctrine DBAL позволяет вам определить свой собственный класс подключения.
doctrine:
dbal:
wrapper_class: AppDBALMyConnectionWrapper
Вы можете реализовать дочерний класс DoctrineDBALConnection
и переопределить 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);
}
}
Ответ №2:
Пожалуйста, ознакомьтесь с этой документацией Symfony: прослушиватели и подписчики событий Doctrine, чтобы понять следующий код
Вот как я это делал для каждого обновления, чтобы обновить время обновления:
<?php
namespace AppEventListener;
use AppEntityAbstractEntity;
use AppEntityUser;
use DoctrineCommonEventSubscriber;
use DoctrineORMEvents;
use DoctrinePersistenceEventLifecycleEventArgs;
use Exception;
use Stringable;
use SymfonyComponentSecurityCoreAuthenticationTokenStorageTokenStorageInterface;
use SymfonyComponentSecurityCoreUserUserInterface;
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 amp;amp; $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 amp;amp; $this->getUser() instanceof User) {
$object->setUpdateUser($this->getuser()->getLastName() . ' ' . $this->getuser()->getLastName() . ' (' . $this->getuser()->getId() . ')');
$object->setUpdateDate();
}
}
}
И добавьте в service.yaml:
AppEventListenerDatabaseActivitySubscriber:
tags:
- { name: 'doctrine.event_subscriber' }
Комментарии:
1. Спасибо за ваш ответ. Но я не вижу, чтобы вы вводили / изменяли какой-либо sql-запрос в своем коде? 🙂
2. Все мои сущности расширяют абстрактность. Поэтому, когда я обновляю один из них, я устанавливаю UpdateUser и UpdateDate в функции preupdate. Это изменение автоматически преобразуется в dql / sql
3. Jep, но вопрос заключается в том, как расширять каждый запрос перед его отправкой, а не в получении обновлений при изменении объектов 🙂