Routing with Zend Framework 2 Restful Webservice - rest

I want to implement a RESTful webservice by using Zend Framework 2, more precisely 2.1.5. I got a 404 if I visit http://ehcserver.localhost/rest, the corresponding message is 'rest(resolves to invalid controller class or alias: rest)'. What went wrong?
You can see my source code in my github-repository:
https://github.com/Jochen1980/EhcServer/blob/master/module/Application/config/module.config.php
The route is defined like this:
return array(
'router' => array(
'routes' => array(
'rest' => array(
'type' => 'ZendMvcRouterHttpSegment',
'options' => array(
'route' => '/:controller[.:formatter][/:id]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'formatter' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[a-zA-Z0-9_-]*'
),
),
),
'home' => array(
...

Your route doesn't define a namespace to which the controller belongs, you need to add a __NAMESPACE__ to route defaults
'rest' => array(
'type' => 'ZendMvcRouterHttpSegment',
'options' => array(
'route' => '/:controller[.:formatter][/:id]',
'defaults' => array(
// tell the router which namespace :controller belongs to
'__NAMESPACE__' => 'Application\Controller',
),
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'formatter' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[a-zA-Z0-9_-]*'
),
),
),

Are you sure the type is valid?
type' => 'ZendMvcRouterHttpSegment',
to this
type' => 'Segment',

Related

Routing in the Zend Framework 2

It's not long since I'm using Zend Framework 2 and I'm trying to write a route for a product that have the rule something like that:
/[slug]-test[ID][av|ai|cv|ci|svb|sib|svc|sic|svi|sii|tv|ti]
An exemple for this rule would look like this:
/freezer-in-good-shape-test12345cv
I try to this with REGEX:
'details' => array(
'type' => 'Zend\Mvc\Router\Http\Regex',
'options' => array(
'route' => '(?<slug>[a-zA-Z0-9_-]+)-test(?<id>[0-9]+)(?<sufix>(av|ai|cv|ci|svb|sib|svc|sic|svi|sii|tv|ti))',
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'List',
'action' => 'details',
),
'spec' => '%slug%-test%id%%sufix%',
)
),
and with SEGMENT too:
'details' => array(
'type' => 'Segment',
'options' => array(
'route' => '/:slug-test:id:sufix',
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'List',
'action' => 'details',
)
'constraints' => array(
'slug' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]*',
'sufix' => '[av|ai|cv|ci|svb|sib|svc|sic|svi|sii|tv|ti]'
)
)
),
but it's not working. Can anyone tell what is that i'm doing wrong? Thanks!
I’d go with Segment here. The only issue I’ve noticed in your route config is the sufix constraint: instead of [av|ai|…] you should type (av|ai|…).
please try with this-
'details' => array(
'type' => 'Segment',
'options' => array(
'route' => '/:slug[-test]:id:sufix',
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'List',
'action' => 'details',
)
'constraints' => array(
'slug' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]*',
'sufix' => '[av|ai|cv|ci|svb|sib|svc|sic|svi|sii|tv|ti]'
)
)
),
on this line 'route' => '/:slug-test:id:sufix',
you had the issues, as it considers "slug-test" as single variable.
so for this you should separate "-test" with "slug" variable.
'route' => '/:slug[-test]:id:sufix',

Zend Framework 2 routing error: resolves to invalid controller class or alias

I'm trying to learn Zend Framework 2 and I have their skeleton application up and running. In order to access it I visit http://localhost:8080/. When visiting that link it displays their generic Zend page. What I want to be able to do is visit http://localhost:8080/application/test and have it bring me to a different page with a different layout.
Here is the module.config.php
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* #link http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
* #copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* #license http://framework.zend.com/license/new-bsd New BSD License
*/
return array(
'router' => array(
'routes' => array(
'home' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/',
'defaults' => array(
'controller' => 'Application\Controller\Index',
'action' => 'index',
),
),
),
// The following is a route to simplify getting started creating
// new controllers and actions without needing to create a new
// module. Simply drop new controllers in, and you can access them
// using the path /application/:controller/:action
'application' => array(
'type' => 'Literal',
'options' => array(
'route' => '/application',
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
),
)
),
'service_manager' => array(
'abstract_factories' => array(
'Zend\Cache\Service\StorageCacheAbstractServiceFactory',
'Zend\Log\LoggerAbstractServiceFactory',
),
'aliases' => array(
'translator' => 'MvcTranslator',
),
),
'translator' => array(
'locale' => 'en_US',
'translation_file_patterns' => array(
array(
'type' => 'gettext',
'base_dir' => __DIR__ . '/../language',
'pattern' => '%s.mo',
),
),
),
'controllers' => array(
'invokables' => array(
'Application\Controller\Index' => 'Application\Controller\IndexController'
),
),
'view_manager' => array(
'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => array(
'layout/layout' => __DIR__ . '/../view/layout/layout.phtml',
'application/index/index' => __DIR__ . '/../view/application/index/index.phtml',
'error/404' => __DIR__ . '/../view/error/404.phtml',
'error/index' => __DIR__ . '/../view/error/index.phtml',
),
'template_path_stack' => array(
__DIR__ . '/../view',
),
),
// Placeholder for console routes
'console' => array(
'router' => array(
'routes' => array(
),
),
),
);
In order to make it work for me this is what I tried:
First I created a controller named TestController in Application/src/Application/Controller/.
Next I added 'application/test/index' => DIR . '/../view/application/test/index.phtml' to the template_map array in view_manager.
I also added 'Application\Controller\Test' => 'Application\Controller\TestController' to the controllers array.
When I visit http://localhost:8080/application/test I get the error:
test(resolves to invalid controller class or alias: test)
I'm obviously doing something wrong but tbh the documentation on Zend is not newb friendly at all and it's becoming very frustrating. Could someone point me in the correct direction? There's just so much configuration that I'm sure I'm missing something small. Thanks!
At the moment the route named application (the parent) defines a URL route of /application. The child route default however requires the controller name to be passed in as the first argument, followed by
action.
This means the URL would be
/application/[:controller]/[:action]
So visting
/application/test
You are inadvertently trying to fetch the 'test' controller; hence the error.
Resolves to invalid controller class or alias : test
To resolve this I would strongly recomend against using the a :controller route parameter but instead use a route per controller action.
'application' => [
'type' => 'Literal',
'options' => [
'route' => '/application',
'defaults' => [
'controller' => 'Application\Controller\Index',
'action' => 'index',
],
'may_terminate' => true,
'child_routes' => [
'test' => [
'type' => 'Literal',
'options' => [
'route' => '/test',
'defaults' => [
// controller value is inherited from parent!
'action' => 'test',
],
],
],
],
],
],

How to add a Restful controller in a Zend module

I'm actually working on a zend framework 2 application which should render two sorts of View :
a view model
a json model
I would include the restful controller in my module but I don't understand if it's possible or recommended.
If someone has been already confronted to a same case, does he could bring me some explanations because I'm searching an answer since 2 days fruitlessly.
In my module.config.php I have :
return array(
'controllers' => array(
'invokables' => array(
'Role\Controller\Role' => 'Role\Controller\RoleController',
'Role\Controller\RoleRest' => 'Role\Controller\RoleRestController',
),
),
'router' => array(
'routes' => array(
'role' => array(
'type' => 'segment',
'options' => array(
'route' => '/role[/:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
'controller' => 'Role\Controller\Role',
'action' => 'index',
),
),
),
'role-rest' => array(
'type' => 'segment',
'options' => array(
'route' => '/role-rest[/:id]',
'constraints' => array(
'id' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
'controller' => 'Role\Controller\RoleRest',
'action' => 'getList',
),
),
),
),
),
'view_manager' => array(
'strategies' => array(
'ViewJsonStrategy',
),
'template_path_stack' => array(
'role' => __DIR__ . '/../view',
),
),
);
and when i try to get myApplication.localhost/role-rest, the page displays the following message :
"The requested controller was unable to dispatch the request.
Controller:
Role\Controller\RoleRest"
I resolve the problem with a simple change in the id's regex constraint :
'constraints' => array(
'id' => '[a-zA-Z0-9_-]*',
),

Automatic convention-based routing within a module in Zend Framework 2--possible?

I'm trying to understand all the configuration necessary to get my routing working in Zend Framework 2, and I can't help but wonder if I am making this more complicated than necessary.
I am working on a simple app that will follow a very simple convention:
/:module/:controller/:action
I've already created and wired up my module, "svc" (short for "service)". I then created a second controller, the "ClientsController", and I can't get the routing to pass through my requests to, e.g., /svc/clients/list to ClientsController::listAction().
As I'm wading through hundreds of lines of configuration, in deeply nested arrays, I'm thinking--isn't there some way to just have a default mapping of my URLs to /:module/:controller/:action ?
Thanks for any assistance. I'm going off of the Zend Framework 2 Quick Start, which walked me through creating a new module and then adding a controller to that module. But when I tried to add second controller to that module, I am tripping over the routing.
Update: I didn't catch this the first time through, but apparently this is supposed to be a feature of the Zend Framework Skeleton app. From the quick start guide:
ZendSkeletonApplication ships with a “default route” that will likely
get you to this action. That route basically expects
“/{module}/{controller}/{action}”, which allows you to specify this:
“/zend-user/hello/world”
That's exactly what I want! But I can't get it to work.
It lists an incomplete module.config.php, with a comment at the bottom about putting "other configuration" here. I tried to figure out what that "other configuration" is, and wound up with this:
return array(
'svc' => array(
'type' => 'Literal',
'options' => array(
'route' => '/svc',
'defaults' => array(
'controller' => 'svc\Controller\Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
),
'controllers' => array(
'invokables' => array(
'svc\Controller\Clients' => 'svc\Controller\ClientsController',
),
),
'view_manager' => array(
'template_path_stack' => array(
'album' => __DIR__ . '/../view',
),
),
);
JFYI, here is what my controller looks like.
namespace svc\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class ClientsController extends AbstractActionController {
public function indexAction() {
return new ViewModel();
}
public function anotherAction(){
return new ViewModel();
}
}
My routes are not working. I get "route not found" when I try to pull up any of my routes.
It lists an incomplete module.config.php, with a comment at the bottom about putting "other configuration" here. I tried to figure out what that "other configuration" is, and wound up with this:
If your module.config.php really looks like that then it won't work, routes is an array of routes defined in the router key, your config contains no such spec, try replacing it with this
return array(
// routes
'router' => array(
'routes' => array(
'svc' => array(
'type' => 'Literal',
'options' => array(
'route' => '/svc',
'defaults' => array(
'controller' => 'svc\Controller\Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
// add the default namespace for :controllers in this route
'__NAMESPACE__' => 'svc\Controller',
),
),
),
),
),
),
),
'controllers' => array(
'invokables' => array(
'svc\Controller\Clients' => 'svc\Controller\ClientsController',
),
),
'view_manager' => array(
'template_path_stack' => array(
'album' => __DIR__ . '/../view',
),
),
);

How to redirect with GET query in Zend 2?

I can redirect to matchable routes like $this->redirect()->toRoute('controller', array('action' => 'something', 'foo' => 'bar')), but how can I append a get query? I'm using it for a filter for a table. The filter can either be submitted on the page (form get method), or linked from another page (need to add get query).
try this :
'course' => array(
'type' => 'Segment',
'options' => array(
'route' => '/course[/:action[/:id]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '\d+'
),
'defaults' => array(
'__NAMESPACE__' => 'Home\Controller',
'controller' => 'course',
'action' => 'index',
'id' => 0
),
),
'may_terminate' => true,
'child_routes' => array(
'query' => array(
'type' => 'Query',
'options' => array(
'route' => '?[:filterByDepartment]'
),
),
),
),
make sure the route is met your need in the view :
echo $this->url('course/query', array('controller'=>'course', 'action'=>'index', 'id'=>0, 'filterByDepartment'=>'depA'));
if this is right, let's try the following in the controller action :
$this->redirect()->toRoute('course/query', array('controller'=>'course', 'action'=>'index', 'id'=>0, 'filterByDepartment'=>'depA'));