Reputation: 105
I'm trying to implement a REST API to my website.
My problem is that the default Zend routing gets in the way. I've first tried using Zend_Rest_Route but I haven't been able to understand how I was supposed to use it correctly for "deep" routes, aka website/api/resource1/filter/resource2/id.
Using the default Zend routing, I'd need to create a gigantic Resource1Controller to take care of all the possible actions, and I don't think it's the "good" way to do this.
I've tried using Resauce ( http://github.com/mikekelly/Resauce/), creating an api module and adding routes, but I'm not able to get it working correctly :
The patterns I added were :
$this->addResauceRoutes(array(
'api/resource' => 'resource',
'api/resource/:id' => 'custom',
'api/resource/filter' => 'resource-filter',
'api/resource/filter/:id' => 'custom',
));
Which then leads to this :
public function addResauceRoutes($routes) {
$router = Zend_Controller_Front::getInstance()->getRouter();
foreach ($routes as $pattern => $controller) {
$router->addRoute($controller,
new Zend_Controller_Router_Route($pattern, array(
'module' => 'api',
'controller' => $controller
)
)
);
}
Zend_Controller_Front::getInstance()->setRouter($router);
What solution is there for me to correctly create my API ? Is there a good way to do this with Zend_Rest_Route ?
Edit : Mike,
I felt that it was not appropriate for me to use different controllers since I need the pathes "website/api/resource/:id" and "website/api/resource/filter/:id" to give me almost the exact same result (the only difference is that because the filter is there, I may get a message telling "content filtered" here).
I thought it was a waste creating another almost identical controller when I could've used the same controller and just checked if a parameter "filter" was present.
However, I don't want to use the basic Zend routing since for the path "website/api/resource/filter/resource2" I'd like to have a totally different comportment, so I'd like to use another controller, especially since I'm trying to use Zend_Rest_Action and need my controllers to use the basic actions getAction(), putAction(), postAction() and deleteAction().
Upvotes: 1
Views: 2176
Reputation: 3352
Please could you explain why it is you need two URI patterns pointing to the same controller. A better solution might be to use a separate controller for each of the two patterns and move any shared logic into your model.
Forcing a unique controller for each routing pattern was an intentional design decision, so I'd be interested to hear more detail about your use case where you feel this isn't appropriate.
I thought it was a waste creating another almost identical controller when I could've used the same controller and just checked if a parameter "filter" was present.
Personally, I think it is cleaner to move the shared logic into the model and to keep your controllers skinny. To me it's not wasteful, it's just more organised - it will make your code easier to manage over time.
If you really need to use the same controller you could always use a query parameter instead, that would work fine:
api/resource/foo?filter=true
That URI would be taken care of by the first route ('api/resource/:id' => 'custom') for free.
But please consider using two controllers, I think that is a better approach.
Upvotes: 1
Reputation: 105
Okay, the reason I didn't get the good controllers was because Resauce uses the controller name as the name of the route, which has to be unique - so second url pointing to "custom" controller couldn't work. Now I'm able to get the files I want :)
So instead of what was previously noted, I use directly the $router->addRoute(); and define new names each times, even if pointing to the same controller.
Example :
$router->addRoute('resource', new Zend_Controller_Router_Route('/api/resources/:id', array('module' => 'api', 'controller' => 'resource')));
$router->addRoute('resourceFiltered', new Zend_Controller_Router_Route('/api/resources/filter1/:id', array('module' => 'api', 'controller' => 'resource', 'filter' => 'filter1'));
Upvotes: 0