Search code examples
parametersconstructorrequestzend-framework2

Get request parameters in controller's constructor Zend Framework 2


I have 10 actions in one Controller. Every action required ID from request. I want to check ID in constructor for every action, so I want avoid to write the same code 10 times in every action.

obviously, In constructor I can not use functions like:

$this->params()->fromQuery('paramname'); or 
$this->params()->fromRoute('paramname');

So, the question is how to get request params in controller's constructor?


Solution

  • Short answer: you cannot. The plugins (you are using params here) are available after construct, unfortunately.

    There are two ways to make your code DRY: extract a method and perform extraction with the event system.

    Extract method: the most simple one:

    class MyController
    {
        public function fooAction()
        {
            $id = $this->getId();
    
            // Do something with $id
        }
    
        public function barAction()
        {
            $id = $this->getId();
    
            // Do something with $id
        }
    
        protected function getId()
        {
            return $this->params('id');
        }
    }
    

    Or if you want to hydrate the parameter directly, this is how I do this quite often:

    class MyController
    {
        protected $repository;
    
        public function __construct(Repository $repository)
        {
            $this->repository = repository;
        }
    
        public function barAction()
        {
            $foo = $this->getFoo();
    
            // Do something with $foo
        }
    
        public function bazAction()
        {
            $foo = $this->getFoo();
    
            // Do something with $foo
        }
    
        protected function getFoo()
        {
            $id  = $this->params('id');
            $foo = $this->repository->find($id);
    
            if (null === $foo) {
                throw new FooNotFoundException(sprintf(
                'Cannot find a Foo with id %s', $id
                ));
            }
    
            return $foo;
        }
    }
    

    With the event sytem: you hook into the dispatch event to grab the id and set it prior to execution of the action:

    class MyController
    {
        protected $id;
    
        public function fooAction()
        {
            // Use $this->id
        }
    
        public function barAction()
        {
            // Use $this->id
        }
    
        protected function attachDefaultListeners()
        {
            parent::attachDefaultListeners();
    
            $events = $this->getEventManager();
            $events->attach(MvcEvent::EVENT_DISPATCH, array($this, 'loadId'), 100);
        }
    
        public function loadId()
        {
            $this->id = $this->params('id');
        }
    }
    

    This feature works as upon dispatch, the loadId() method is executed and then the other (fooAction/barAction) method is ran.