1

I want to store in my database all the user actions done about an entity.

For example, for 1 entity, I want to store :

  • Created by (= author)
  • Updated by
  • Date of creation
  • Date of update

I want to store the history of the actions of a user, not the last ones. I thought I could create a table with these columns :

  • log_id
  • user_id
  • entity_id
  • action (= "create" or "update" or something else)
  • date

And then, I could easily get the last update of my entity and display the date and the user who did it.

Is there a Symfony bundle to do this ? Should I use Monolog ? I will do this for many entities and I'm not sure if this is the correct way to do...

Is it possible to create only one logs table to store each log about each entity ? It bothers me to create 1 logs table per entity.

Eve
  • 776
  • 2
  • 11
  • 32

2 Answers2

2

Since Doctrine is event based, it's easy:

  1. Either use an extension, like Gedmo Loggable

  2. Or hook into Doctrine's events and log, using Monolog, everything that happens in your app.

Personally I would prefer option 2 since I'm a control maniac, it's a little more complex though. Personally I would also use Monolog so I could abstract away the way how and where the log entries are stored.

When you decide how to approach this and you will need any assistance along the way, please ask another question.

Good luck.

Mike Doe
  • 16,349
  • 11
  • 65
  • 88
  • Thank you for your answer. Gedmo Loggable seems to be good but maybe Monolog is better, as you said, because it's more flexible... I will test it. – Eve Jun 28 '19 at 12:09
  • If I did help please consider upvoting my answer. Down to your comment: gedmo loggable is a Doctrine extension (mind it writes to a SQL table) and Monolog is a log abstraction library, both are totally different things. – Mike Doe Jun 28 '19 at 12:47
2

I don't know if that would fit what you need, but you could easily add a Listener to the symfony kernel to log every controller used.

Something like this :

class UserLogListener {

    protected $authChecker;
    protected $tokenStorage;
    protected $entityManager;

    public function __construct(TokenStorageInterface  $tokenStorage, AuthorizationChecker $authChecker, EntityManager $entityManager)
    {
        $this->authChecker = $authChecker;
        $this->tokenStorage = $tokenStorage;
        $this->entityManager = $entityManager;

    }

    public function onKernelRequest(GetResponseEvent $event)
    {
        if( $this->tokenStorage->getToken() != null){
            $user = $this->tokenStorage->getToken()->getUser();
            $currentDate = new \Datetime();
            $action = $event->getRequest()->attributes->get('_controller');
            $method =  $event->getRequest()->getMethod();
            $userIp =  $event->getRequest()->getClientIp();
            $userLogRepository = $this->entityManager->getRepository(UserLog::class);

            if($user instanceof User){
                $userLog = new UserLog();
                $userLog->setUser($user);
                $userLog->setIp($userIp);
                $userLog->setAction($action);
                $userLog->setMethode($method);
                $userLog->setDate($currentDate);
                if($event->getRequest()->request && $methode=='POST'){
                    $userLog->setData(json_encode($event->getRequest()->request->all()));
                }else{
                    $userLog->setData($event->getRequest()->getPathInfo());
                }
                $this->entityManager->persist($userLog);
                $this->entityManager->flush();
            }
        }

    }
}

What it does is add to the database (with an entity called UserLog) information about every page called. So you can know which action is made by knowing which controller is called, and you can also log the request data so you can find out what modification/creation the user did.

Dylan KAS
  • 4,840
  • 2
  • 15
  • 33
  • Sounds nice, thank you. I'm not sure I can find easily the last update for each entity (if I want to display it inside lists for example) with this method. Anyway I will test it. – Eve Jun 28 '19 at 12:04