Search code examples
symfonysymfony-2.7propel2

Propel2, createdBy field


Let's say I have model "Question". Every question is created by user (current user). How to "auto" update createdBy to current.user

In Doctrine2 I should have event listener with dependency on security.context. And event will subscribe for preSave(), setting $question->setCreatedBy( $context->getToken()->getUser());

How to achieve this with Propel2 ? I could set createdBy in controller, but this is ugly :(

I could write custom behavior, but how to access security.context from the behavior ?


Solution

  • After ~ half year I found working solution :)

    Idea: Model will have setter injection for Event Dispatcher. On pre-save model will fire event (validation/user injection etc..). This way I require ED for save. I can select objects from the DB without injected ED. Dependency manager will manage "repository". Repo will be able to inject all required dependencies on the model and then call save. $depepndanciesManager->getModelRepo->save($model). Witch will do: $model->setEventDispacher($this->getEventDispacher); $model->save();

    Example of Model:

    class Lyric extends BaseLyric
    {
        private $eventDispacher;
    
        public function preSave(ConnectionInterface $con = null)
        {
            if (!$this->validate()) {
                // throw exception
            }
    
            $this->notifyPreSave($this);
            return parent::preSave($con);
        }
    
        private function getEventDispacher()
        {
            if ($this->eventDispacher === null) {
                throw new \Exception('eventDispacher not set');
            }
            return $this->eventDispacher;
        }
        public function setEventDispacher(EventDispacher $eventDispacher)
        {
            $this->eventDispacher = $eventDispacher;
        }
        private function notifyPreSave(Lyric $lyric)
        {
            $event = new LyricEvent($lyric);
            $this->getEventDispacher()->dispatch('tekstove.lyric.save', $event);
        }
    }
    

    Example of Repository:

    class LyricRepository
    {
        private $eventDispacher;
    
        public function __construct(EventDispacher $eventDispacher)
        {
            $this->eventDispacher = $eventDispacher;
        }
    
        public function save(Lyric $lyric)
        {
            $lyric->setEventDispacher($this->eventDispacher);
            $lyric->save();
        }
    }
    

    Example usage from controller:

    public function postAction(Request $request)
    {
        $repo = $this->get('tekstove.lyric.repository');
        $lyric = new \Tekstove\ApiBundle\Model\Lyric();
        try {
            $repo->save($lyric);
            // return ....
        } catch (Exception $e) {
            // ...
        }
    }
    

    Example config:

    tekstove.lyric.repository:
        class: Tekstove\ApiBundle\Model\Lyric\LyricRepository
        arguments: ["@tekstove.event_dispacher"]
    

    Config is based on symfony framework. Real implementation:

    Links may not work, project is in active development!