7

Zend Framework 1 had a very simple way of parsing URL routes and setting found params in the $_GET superglobal for easy access. Sure, you could use ->getParam($something) inside the controller, but if the param was found in the URL, it was also accessible via $_GET.

Example for url mypage.com/mymodule/mycontroller/myaction/someparam/5:

ZF1

$this->getParam('someparam'); // 5
$_GET['someparam']; // 5

ZF2

$this->getEvent()->getRouteMatch()->getParam('someparam'); // 5
$_GET['someparam'] // undefined index someparam

Obviously, the difference is that ZF2 does NOT put the route params into the $_GET superglobal.

How do I make it put the parsed parameters into the $_GET superglobal, since extending the controller and just defining a constructor that does that is out of the question (because RouteMatch is not an object yet and cannot be called from the controller's constructor)?

Calling $_GET = $this->getEvent()->getRouteMatch()->getParam('someparam'); in every one of my controllers would work, but I don't want that.

In other words, following the example URL from above, I want to be able to do $_GET['someparam'] and still get the value "5" in any component in the application.

Edit: Looks like I wasn't clear enough, so I'll try to clarify some more. I want whatever param I enter in the URL via /key/value formation to be available in $_GET instantly. I don't really have a problem with getting the param, I know how to get it and I extended Zend's controller so I can just call $this->getParams again like in ZF1, and now all controllers extend that one, I just want the params from the URL to automatically be in $_GET as well, so I can access them easily in third party components which use $_GET natively.

Edit 2: Updated as reaction to Samuel Herzog's answer: I don't really mind invalidating the SRP in this case, because the libraries are built in such a way that they need direct access to $_GET - they do their own filtering and directly depend on this superglobal. They also directly fetch $_FILES and $_POST for processing, it's just the way their code works.

I've made the following method in the abstract controller: $this->mergeGet(); which basically makes $_GET absorb all the route matched params and everything works as intended, but seeing as the libraries will be required in every controller/action, it might get tedious to call that method every time. If only the controller had an init() method like in ZF1...

Swader
  • 11,387
  • 14
  • 50
  • 84
  • 1
    Not sure enough for an answer, try `->params('key', $defaultValue)` on either the Controller or Request, i think this is the one you're looking for. – Sam Aug 06 '12 at 04:56
  • I have no problem fetching the param, my worry is a different one. Please see edited question – Swader Aug 06 '12 at 05:55
  • 1
    @Sam its `Controller::Params('key', $default)` which calls a Controller Plugin (Params) to prevent you from writing `Controller::getEvent()->getRouteMatch()->getParam(...)`. – Samuel Herzog Aug 06 '12 at 16:47

3 Answers3

13

In ZF2, Im using this

$getparams = $this->getRequest()->getQuery();
eli_daxs
  • 176
  • 1
  • 10
8

First of all, you shouldn't use $_GET or any other superglobal directly if you're building on an object oriented stack. The SRP is invalidated this way.

If you have no possibility to change the way of your (3rd party?) librarys to change you might want to hook into the MvcEvent, listen to --event-- and then get the RouteMatch, you may fill $_GET with a simple loop.

For a most-performant answer, you should know if the named library will be needed for every action, just for one module, or only in certain controllers/actions. If the latest is your use-case, you should write a controller plugin instead.

some example code for the first approach:

namespace YourModule;
use Zend\EventManager\EventInterface as Event;
use Zend\Mvc\MvcEvent;

class Module
{
    ...

    public function onBootstrap(Event $ev)
    {
        $application = $e->getApplication();
        $eventManager = $application->getEventManager();

        $eventManager->attach('route', function(MvcEvent $mvcEvent) {
            $params = $mvcEvent->getRouteMatch()->getParams();

            foreach ( $params as $name => $value )
            {
                if ( ! isset($_GET[$name]) 
                {
                    $_GET[$name] = $value;
                }
            }
        });
    }
}
Samuel Herzog
  • 3,561
  • 1
  • 22
  • 21
  • 1
    Thanks for the update @Swader, each Modules onBootstrap event gets called on every request. So if there is a request /shop/product/milk and the sample code is in the Application but not the Shop module it will be called regardless! listening to the route event at one central place (Your Application/Module.php) will do the trick perfectly. – Samuel Herzog Aug 06 '12 at 19:40
  • Ok, this is typical ZF, there is zero documentation on how to listen to the bootstrap event in the Module class, could you drop me a hint please? Perhaps put it in the answer so I can mark it as accepted if it does what I want it to do? – Swader Aug 07 '12 at 07:37
  • Documentation is in progress, thats why it's only RC atm ;) The code i provide does exactly this. see: `$eventManager->attach('route', function(MvcEvent $e) { ...` just an anonymous function as listener attached. – Samuel Herzog Aug 07 '12 at 11:40
  • See my answer here http://stackoverflow.com/a/11633167/923847 for easier and up to date param fetching. – Matsemann Aug 07 '12 at 12:41
  • Ah, but curiously it gives me this: Fatal error: Call to undefined method Zend\Mvc\Router\Http\TreeRouteStack::getRouteMatch() in /Users/swader/Sites/stm/module/Application/Module.php on line 23, the same error as if I had tried to call the $_GET merge inside the constructor of the main controller abstract. – Swader Aug 07 '12 at 13:45
  • 1
    ouch, my bad. There is no need to access the router first, it's just `$e->getRouteMatch()->getParams();` see [the Docs on MvcEvent](http://zf2.readthedocs.org/en/latest/modules/zend.mvc.mvc-event.html). As the `route`-Event is thought for routers you maybe want to listen at very low priority (e.g. -1000) or listen to `dispatch` (the route is definitly set) with very high priority instead. – Samuel Herzog Aug 08 '12 at 00:38
  • @Sam, can you please explain more why SRP is invalidated when using GET? – Dennis Oct 07 '15 at 17:49
  • can anyone explain why SRP is invalidated when using raw GET? – Dennis Aug 04 '17 at 15:02
  • @Dennis Knowing about the channel for parameters is a responsibility, you likely want this in a dedicated class. If you use raw GET, you'll couple all your classes to this input method. If you need to validate or transform the GET variables, you'll then have validation/transformation wherever you've used GET, thereby adding additional responsibility to all these classes. – Samuel Herzog Aug 07 '17 at 10:33
1

You could use in your controlller:

 $paramValue = $this->params()->fromQuery('your_param_here');

Regards

Nicolas Finelli
  • 2,170
  • 1
  • 14
  • 9