<?php
namespace App\Subscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Security;
use Doctrine\ORM\AbstractQuery;
use App\Controller\ActionLogController;
use App\Entity\AdminAction;
use App\Entity\AdminLog;
class ActionLogSubscriber implements EventSubscriberInterface
{
public function __construct(
private EntityManagerInterface $entityManager,
private Security $security,
){}
public function onKernelController(ControllerEvent $event)
{
try {
$controller = $event->getController();
// when a controller class defines multiple action methods, the controller
// is returned as [$controllerInstance, 'methodName']
if (!$controller[0] instanceof ActionLogController) {
return;
}
$postData = json_decode($event->getRequest()->getContent(), true);
if (!$postData) $postData = $event->getRequest()->request->all();
if (!$postData) $postData = $event->getRequest()->attributes->all();
//过滤屏蔽数据 先写死
foreach ($postData as $k => $v) {
if ($k == 'password') $postData[$k] = '****';
}
$entityClass = $controller[0]::getEntityClass();
if (($postData['id'] ?? null) && $entityClass) {
$rawData = $this->entityManager->getRepository($entityClass)->createQueryBuilder('u')
->andWhere('u.id = :id')->setParameter('id', $postData['id'])
->setMaxResults(1)->getQuery()->getOneOrNullResult(AbstractQuery::HYDRATE_ARRAY)
;
}
$event->getRequest()->attributes->set('requestData', [
'rawData' => $rawData ?? [], //原始数据
'postData' => $postData, //提交的数据
'entityClass' => $entityClass, //entity
'actionLog' => true, //是否记录
]);
} catch (\Throwable $e) {
}
}
public function onKernelResponse(ResponseEvent $event)
{
try {
//记录当前请求及返回信息
$request = $event->getRequest();
$requestData = $request->attributes->get('requestData');
if ($requestData['actionLog'] ?? false) {
$resp = json_decode($event->getResponse()->getContent(), true);
$route = $this->entityManager->getRepository(AdminAction::class)->findOneBy(['routerName'=>$request->attributes->get('_route')]);
$adminLog = new AdminLog();
$adminLog->setAdmin($this->security->getUser());
$adminLog->setRequestUri($request->getRequestUri());
$adminLog->setMethod($request->getMethod());
$adminLog->setRoute($request->attributes->get('_route'));
$adminLog->setRouteName($route->getName());
$adminLog->setController($request->attributes->get('_controller'));
$adminLog->setRawData($requestData['rawData']);
$adminLog->setPostData($requestData['postData']);
$adminLog->setRespCode($resp['code'] ?? 0);
$adminLog->setRespMessage($resp['message'] ?? 'success');
$adminLog->setIp($request->getClientIp()); //此处是因为使用了nginx的代理 所以这儿获取的nginx proxy的设置
$this->entityManager->persist($adminLog);
$this->entityManager->flush();
}
} catch (\Throwable $e) {
dd($e->getMessage());
}
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::CONTROLLER => 'onKernelController',
KernelEvents::RESPONSE => 'onKernelResponse',
];
}
}