In Zend framework 3, I tried adding new controller "ArticleController" to a existed module City but failed. I post screen shot, my folder structure and module.config.php. Could you explain what the problem is? Incidentally, it worked when accessing http://0.0.0.0:7000/city
When accessing http://0.0.0.0:7000/article
Next, module\city\config\module.config.php codes are following:
<?php
namespace City;
use Zend\Router\Http\Segment;
return [
'router' => [
'routes' => [
'city' => [
'type' => Segment::class,
'options' => [
'route' => '/city[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\CityController::class,
'action' => 'index',
],
],
],
'article' => [
'type' => Segment::class,
'options' => [
'route' => '/article[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\ArticleController::class,
'action' => 'index',
],
],
],
],
],
'view_manager' => [
'template_path_stack' => [
'city' => __DIR__ . '/../view',
],
],
];
Error message is clear. Application doesn't know anything about your controller. Your module config has to have information about controllers under "controllers" key. Checkout zend documentation, you'll see "controllers" key in config file.
Related
I'm refactoring some routing in a project and I'm trying to retain the current path structure of the following...
/events <-- Works
/events/super-bowl <-- Works
/events/2012-super-bowl <-- Doesn't work! Archive Layout
/events/2012-super-bowl/detail-page <-- Doesn't work! Archive sub layout
/events/2018-super-bowl <-- Works. Standard Layout, no sub layout
This is what I have tried...
'router' => [
'routes' => [
'events' => [
'type' => 'literal',
'options' => [
'route' => '/events',
'defaults' => [
'controller' => 'events',
'action' => 'index',
],
],
'may_terminate' => true,
'child_routes' => [
'super-bowl' => [
'type' => 'segment',
'options' => [
'route' => '/super-bowl',
'defaults' => [
'action' => 'superBowl',
],
],
],
'super-bowl-archives' => [
'type' => 'segment',
'options' => [
'route' => '/[:year]-super-bowl[/:detail]',
'constraints' => [
'year' => '^(2012|2013|2014)',
],
'defaults' => [
'controller' => 'super-bowl-archives',
'action' => 'index',
],
],
],
'super-bowl-standard' => [
'type' => 'segment',
'options' => [
'route' => '/[:year]-super-bowl',
'constraints' => [
'year' => '\d{4}'
],
'defaults' => [
'controller' => 'super-bowl-standard',
'action' => 'index',
],
],
],
],
],
],
],
I'm struggling with the archive layouts. I'd like to capture certain years and point them to a different controller. The archives have a sub route as well that I'm not sure how to achieve.
There are two problems in that configuration.
First: matching rule.
Since the matching isn't completely regex based, the correct "pattern" for year is '2012|2013|2014'
Second: matching order.
According to Zend router documentation:
Routes will be queried in a LIFO order, and hence the reason behind the name RouteStack
Last route will be matched first. Since 2012 is matched with \d{4}, you have to first test those "exceptions".
Simply put super-bowl-archives route after super-bowl-standard and it'll work
'router' => [
'routes' => [
'events' => [
'type' => 'literal',
'options' => [
'route' => '/events',
'defaults' => [
'controller' => 'events',
'action' => 'index'
]
],
'may_terminate' => true,
'child_routes' => [
'super-bowl' => [
'type' => 'segment',
'options' => [
'route' => '/super-bowl',
'defaults' => [
'action' => 'superBowl'
]
]
],
'super-bowl-standard' => [
'type' => 'segment',
'options' => [
'route' => '/[:year]-super-bowl',
'constraints' => [
'year' => '\d{4}'
],
'defaults' => [
'controller' => 'super-bowl-standard',
'action' => 'index'
]
]
],
'super-bowl-archives' => [
'type' => 'segment',
'options' => [
'route' => '/[:year]-super-bowl[/:detail]',
'constraints' => [
'year' => '2012|2013|2014'
],
'defaults' => [
'controller' => 'super-bowl-archives',
'action' => 'index'
]
]
]
]
]
]
],
I'm having trouble adding an optional parameter to my home route.
This is my current router:
'routes' => [
'home' => [
'type' => Segment::class,
'options' => [
'route' => '/[:salon/]',
'constraints' => [
'salon' => '[a-zA-Z][a-zA-Z0-9_-]*'
],
'defaults' => [
'controller' => 'Application\Controller\Index',
'action' => 'index',
'salon' => 'test'
],
],
],
'application' => [
'type' => Segment::class,
'options' => [
'route' => '/application[/:controller[/:action]]',
'constraints' => [
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*'
],
'defaults' => [
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Application\Controller\Index',
'action' => 'index',
],
],
'may_terminate' => true,
'child_routes' => [
'default' => [
'type' => 'wildcard'
]
]
],
],
My Controller:
<?php
namespace Application\Controller;
class IndexController extends AbstractController
{
public function indexAction()
{
var_dump($this->params('salon'));
die;
}
}
domain.ltd/
This works and I'm getting default value for salon paramter which is 'test'
domain.ltd/test123
Expected value would be 'test123' but this displays me 404 error: The requested URL could not be matched by routing.
I want to create routes with an optional [lang] parameter that would be used to set the application language as follows:
Example with default lang param(EN for example)
domain.tld/
domain.tld/users
domain.tld/contacts
etc.
Example witt new lang param(DE for examle)
domain.tld/de
domain.tld/de/users
domain.tld/de/contacts
etc.
This is my route configuration:
'router' => [
'routes' => [
'site' => [
'type' => Segment::class,
'options' => [
'route' => '[/:lang]',
'constraints' => [
'lang' => '[a-z]{2}',
],
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'index',
'lang' => 'en',
],
],
'may_terminate' => true,
'child_routes' => [
'home' => [
'type' => Literal::class,
'options' => [
'route' => '/',
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'index',
],
],
'may_terminate' => true,
],
'application' => [
'type' => Segment::class,
'options' => [
'route' => '/application[/:action]',
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'index',
],
],
'may_terminate' => true,
],
],
],
],
]
When I have lang param in the url everything is fine. But when I try to open "default" lang without specifying it into the path (ex. example.tld/application/test) it gives me 404 error.
What I found is that the final regex after transformation from Segment class is (\G(?:/(?P<param1>([a-z]{2})))?) and path is /application/test. When preg_match is executed on Segment.php:385 it return match with following values:
[
'0' => '/ad',
'param1' => 'ad',
'1' => 'ad',
],
which is obviously the wrong behavior. My language is set to "ad" instead of open application/test action. I tested around 10 more regex but without success... (ex. ^[a-z]{2}$).
What I am doing wrong?
You get 404 because URL does not match site route, so child routes of site are skipped.
Try this:
'home' => [
'type' => Segment::class,
'options' => [
'route' => '/[:lang/]',
'constraints' => [
'lang' => '(en|de)?',
],
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'index',
'lang' => 'en',
],
],
'may_terminate' => true,
'child_routes' => [
'application' => [
'type' => Segment::class,
'options' => [
'route' => 'application[/:action]',
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'index',
],
],
],
],
]
If you do not provide lang param then it takes default (en in my example) param.
Example:
example.tld/application/test
lang is en
controller is IndexController
action is test (testAction())
example.tld/de/application/test
lang is de
controller is IndexController
action is test (testAction())
In ZF3 I want to get default parameter from route. I'm getting parameters in this way in controller:
$params = $this->params()->fromRoute('crud');
My urls looks like this:
1: somedomain/admin/color/add
2: somedomain/admin/color
In 1) I'm getting add in my $params variable.
In 2) I'm getting null but I'm expecting default (in this case view)
I think this is problem with bad router configuration.
'admin' => [
'type' => Segment::class,
'options' => [
'route' => '/admin/:action',
'defaults' => [
'controller' => Controller\AdminController::class,
'action' => 'index',
],
],
'may_terminate' => true,
'child_routes' => [
'color' => [
'type' => Segment::class,
'options' => [
'route' => '/:crud',
'constraints' => [
'crud' => 'add|edit|delete|view',
],
'defaults' => [
'controller' => Controller\AdminController::class,
'crud' => 'view',
],
],
],
],
],
In your route definition, you didn't says the router that your crud parameter is optionnal. So when you call somedomain/admin/color, it is the route /admin/:action which is selected.
To specify a optional parameter, use the bracket notation (assuming you use the same action):
'admin' => [
'type' => Segment::class,
'options' => [
'route' => '/admin/:action[/:crud]',
'defaults' => [
'controller' => Controller\AdminController::class,
'action' => 'index',
'crud' => 'view',
],
'constraints' => [
'crud' => 'add|edit|delete|view',
],
],
],
I am trying to set two different routes to handle pagination of data, for instance:
'error' => [
'type' => 'Segment',
'options' => [
'route' => '/error[/:action][/:id][page/:page]',
'constraints' => [
'page' => '[0-9]*',
'id' => '[0-9]*',
],
'defaults' => [
'controller' => 'Admin\Controller\Error',
'action' => 'index',
],
],
],
'paginator' => [
'type' => 'Segment',
'options' => [
'route' => '/blog/list-entries/[page/:page]',
'constraints' => [
'page' => '[0-9]*',
],
'defaults' => [
'controller' => 'Admin\Controller\Blog',
'action' => 'list-entries',
],
],
],
In the error route, the paginator works for the first set of data, but when I try to go to the next page to view more data it uses /blog/list-entries/page/2 instead of the /error/[/:action][/:id][page/:page] route. Is the paginator route becoming the default route for more data?
Any help would be appreciated.
Thanks
Fixed the issue, I was passing the wrong paginator route in the view. Thanks!