0

I am developping some kind of cronjob monitoring on our symfony2 application.

I created a CommandExecution entity with a 'completed' property.

I'm using console events to create and persist this entity.

My service :

kernel.listener.console:
        class: Evo\CronBundle\EventListener\ConsoleListener
        arguments: [@doctrine.orm.entity_manager]
        tags:
            - { name: kernel.event_listener, event: console.command, method: onConsoleCommand }
            - { name: kernel.event_listener, event: console.terminate, method: onConsoleTerminate }
            - { name: kernel.event_listener, event: console.exception, method: onConsoleException }

and the ConsoleListener:onConsoleCommand() and ConsoleListener:onConsoleTerminate() methods called when a command starts and ends to execute :

public function onConsoleCommand(ConsoleCommandEvent $event)
{
    $command = $event->getCommand();
    $commandEntity = $this->em->getRepository('EvoCronBundle:Command')->findOneBy(['name' => $command->getName()]);

    $commandExecution = new CommandExecution();
    $commandExecution->setCommand($commandEntity);

    $this->em->persist($commandExecution);
    $this->em->flush();

    // here I want to pass my entity to the command, so I can get it back in the onConsoleTerminate() method
    $command->setCommandExecution($commandExecution);
}

public function onConsoleTerminate(ConsoleTerminateEvent $event)
{
    $command = $event->getCommand();

    // here, retrieve the commandExecution entity passed in onConsoleCommand() method
    $commandExecution = $command->getCommandExecution();

    $commandExecution->setCompleted(true);

    $this->em->flush();
}

As you can see in these methods, I would like to add a commandExecution property to the Symfony Component Console\Command\Command.php, so I can pass in my commandExecution entity and change its status.

Do I have to override this component ? If yes, how ? Or can I do it in a simpler way ?

1 Answer 1

1

Add the commandExecution property in your ConsoleListener

protected $commandExecution = null;

Then set it in your onConsoleCommand() method

public function onConsoleCommand(ConsoleCommandEvent $event)
{
    $command = $event->getCommand();
    $commandEntity =     $this->em->getRepository('EvoCronBundle:Command')->findOneBy(['name' =>     $command->getName()]);

    $commandExecution = new CommandExecution();
    $commandExecution->setCommand($commandEntity);

    $this->em->persist($commandExecution);
    $this->em->flush();

    $this->commandExecution = $commandExecution;
}

Then you can access to it in your onConsoleTerminate() method

public function onConsoleTerminate(ConsoleTerminateEvent $event)
{
    $command = $event->getCommand();

    // here, retrieve the commandExecution entity passed in onConsoleCommand() method
    $commandExecution = $this->commandExecution;

    $commandExecution->setCompleted(true);

    $this->em->flush();
}

Don't forget to test if commandExecution value is null in onConsoleTerminate() method

Sign up to request clarification or add additional context in comments.

7 Comments

I thought about it but I didn't even try it because I was pretty sure the entity wouldn't be 'saved' between the 2 event calls. Like if the listener would be re-instanciated before triggering onConsoleTerminated. But it's not, and your solution works perfectly ! Is it related to singleton design pattern ? I know the concept, but never investigated on it. I feel that this event is a singleton. Is it ?
A service is instantiated once when you need it and lives as long as the script is running. But the events are launched each time they have to, for example, if you chained 2 commands, the events will be launched 2 times each, but the listener will still be the same object
Can I access this commandExecution object inside my Command Class ? For example, I would like to update a property of commandExecution with the number of rows affected by the Command. or can I pass a variable from the Command to the ConsoleListener:onCommandTerminate() ?
To do so, you should change the way you listener works: 1) Remove the property commandExecution from the listener and put it in your command class 2) Stop listening consoleCommand and consoleTerminate events 3) Create your own events customConsoleCommand, customConsoleTerminate with the property commandExecution 4) Your listener now listen this custom events, and get commandExecution by using $event->getCommandExecution 5) Don't forget to manually dispatch your event in your command
To dispatch these custom events, I have to trigger them at first and last line of my execute() Command method ? if there is a synthax error in this execute() method, they will still be triggered ?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.