Condition inside route definition - php

I just started to use ZendFramework 2. I defined a route in my module.config.php and I want to use the $this->url in my view to generate the url.
module.config.php
'settings-users-list' => array(
'type' => 'Zend\Mvc\Router\Http\Regex',
'options' => array(
'regex' => '/settings((/role/(?<role>[a-zA-Z]+))|)((/search/(?<search>[a-zA-Z0-9_-]+))|)((/page/(?<page>[0-9]+))|)((/date/(?<date>asc|desc))|)((/log/(?<log>asc|desc))|)',
'defaults' => array(
'controller' => 'Admin\Controller\Settings',
'action' => 'index',
),
'spec' => '/settings/role/%role%/search/%search%/page/%page%/date/%date%/log/%log%',
),
),
In my view
echo $this->url('admin/settings-users-list',$link_params,array('force_canonical' => true));
where
$link_params = array(
'controller' => 'settings',
'action' => 'index',
'role' => 'admin',
'search' => '',
'page' => '',
'date' => '',
'log' => '',
);
My problem is that when a part of my parameters are empty the generated url is not the desired one. In this case the the generated url is:
www.mysite.com/admin/settings/role/admin/search//page//date//log/
Is there a way to not display search, page, date, log if this parameter is not set. Maybe is there a way to put a condition in spec field of settings-users-list route in module.config.php.

In your case I would suggest to not add the search params like search, page, date and log to your route at all. Those are query params and for this ZF2 url helper has a special query key in options. You can also find this in the paragraph Query String Arguments in the ZF2 url view helper documentation. In your case you can use it like this:
$params = array(
'controller' => 'settings',
'action' => 'index',
'role' => 'admin'
);
$query = array(
'search' => '',
'page' => '',
'date' => '',
'log' => ''
);
$options = array(
'force_canonical' => true,
'query' => $query
);
echo $this->url('admin/settings-users-list', $params, $options);
I would also suggest to simplify your router. It will be much more readable without a regex:
'settings' => array(
'type' => 'Literal',
'options' => array(
'route' => '/settings'
)
'may_terminate' => false,
'child_routes' => array(
'role' => array(
'type' => 'Segment',
'options' => array(
'route' => '/role/:role'
'constraints' => array(
'role' => '[a-zA-Z]*'
),
'defaults' => array(
'controller' => 'Application\Controller\Settings',
'action' => 'index',
)
)
)
)
),
Then you can do like this:
echo $this->url('settings/role', $params, $options);

Related

Zend translated routes

I have multiple routes for different locales:
Example:
Route for /de
$routes['industry'] = array(
'route' => 'branche/:type',
'defaults' => array(
'module' => 'default',
'controller' => 'index',
'action' => 'branche',
'type' => 'automobil'
),
'reqs' => array(
'type' => '(automobil|textil)'
)
);
Route for /en
$routes['industry'] = array(
'route' => 'industry/:type',
'defaults' => array(
'module' => 'default',
'controller' => 'index',
'action' => 'branche',
'type' => 'car'
),
'reqs' => array(
'type' => '(car|textile)'
)
);
Its possible somehow to have just one route instead of 2 on this case?
Note is not just the route which changes, also the type on the reqs and the default type.
I see two different routes there
Usually the internationalisation is on the page but not on the url
Let me be clear, you keep your url and with a parameter in the url you know the language of the page so
$routes['industry'] = array(
'route' => 'industry/:lang/:type',
'defaults' => array(
'module' => 'default',
'controller' => 'index',
'action' => 'branche',
'type' => 'car',
'lang' => 'en'
),
'reqs' => array(
'lang' => '(en|de)',
'type' => '(car|textile)'
)
);
and depending of the parameter lang you display the correct message on your twig or phtml or html
Another way to do this changing the url is:
$routes['industry'] = array(
'route' => ':industry/:type',
'defaults' => array(
'module' => 'default',
'controller' => 'index',
'action' => 'branche',
'type' => 'car',
'industry' => 'industry'
),
'reqs' => array(
'industry' => '(industry|branche)',
'type' => '(car|textile)'
)
);
I found the solution for the translations here:
https://dasprids.de/blog/2009/04/01/translated-segments-for-standard-route/

ZF2 Redirect to route with controller action and get param

So I'm trying to redirect my code to another action within a controller http://localhost/salesorder/view?id=5509c273f948e7cf068b456a this view action is working fine. But every time the redirect code runs it redirects me to http://localhost/salesorder?id=5509c273f948e7cf068b456a
I am now clueless what is did I do wrong.
$params = ['controller' => 'SalesOrder',
'action' => 'view',
];
$options = ['query' => ['id' => (string) $orderId]];
return $this->redirect()->toRoute('Salesorder', $params, $options);
My moduleconfig looks like this
'Salesorder' => array(
'type' => 'Literal',
'options' => array(
'route' => '/salesorder',
'defaults' => array(
'__NAMESPACE__' => 'Backend\Controller',
'controller' => 'SalesOrder',
'action' => 'new',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '[/:action]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
'action' => 'new'
),
),
),
),
),
Excuse me that I cannot put a comment since I have not enough reputation, but this may lead you to a solution:
First of all fix the toroute function call to this:
return $this->redirect()->toRoute('Salesorder', array('id'=> (string) $orderId));
Then fix the route specification to this:
'Salesorder' => array(
'type' => 'segment',
'options' => array(
'route' => '/MODULE_NAME/SalesOrder/new/:id[/]',
'constraints' => array(
'id' => '[a-zA-Z0-9_-]*'
),
'defaults' => array(
'controller' => 'MODULE\Controller\SalesOrder',
'action' => 'new',
),
),
),

ZF2 - Issues with $this->url and Routing

I'm having and issue with the view helper function this->url() that doesn't return and url from a child route and I get a White Screen of the dead. When I put the url manually in the browser the router recognizes the url well.
I have this in my module.config.php:
'news' => array(
'type' => 'Segment',
'options' => array(
'route' => '/news[/:id]',
'constraints' => array(
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Application\Controller\News',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'allnews' => array(
'type' => 'Segment',
'options' => array(
'route' => '[/:action[/:tab[/:page]]]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'tab' => '[0-9]+',
'page' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Application\Controller\News',
'action' => 'all',
'tab' => 1,
'page' => 1,
),
),
),
),
),
For example:
/news/2
Works correctly and matches the parent route
And:
/news/all/2/5
Works correctly and matches the child route.
But when I use this in the view-helper I get a White Screen of the Dead:
echo($this->url('news/allnews', array('action' => 'all', 'tab' => '1', 'page' => '1')));
My question is: What it's wrong?? I used this method in others views and worked well.
You do not need to use child routes in combination with Router Segments. One Segment should be sufficient!
'news' => array(
'type' => 'Segment',
'options' => array(
'route' => '/news[/:action[/:id][/:tab][/:page]]',
'constraints' => array(
'id' => '[0-9]+',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'tab' => '[0-9]+',
'page' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Application\Controller\News',
'action' => 'index',
),
),
),
As long as the Defaultcontroller is sufficient you for your needs you also would not need to have it within your params. Once you need more then 1 you prob want to have another constraint defining the controller.
Now you could simply use the url viewhelper in various ways.
if you only need the default action within your default controller you could write it like so.
$this->url('news');
If you need to route to actions with params you could use the viewhelper like so
$this->url('news', array('action' => $action, 'tab' => $tab, 'page' => $page));
Ideally I would use a Router Literal with Router Segments as child routes since bombarding the router segment with tons of constraints gets messy pretty fast.
...
'custom_route' => array(
'type' => 'Literal',
'priority' => 1337,
'options' => array(
'route' => '/custom',
'defaults' => array(
'__NAMESPACE__' => 'Custom\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'custom_child' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action]][/:id]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
),
),
),
),
),
...
Pretty sure this won't help but everything does look right in your routing... Have you tried
$this->url('news/allnews', array('action' => 'all', 'tab' => 1, 'page' => 1))
Don't know how the routing stuff handles contraints on digits and providing strings to url view helper.
You probably either need to enable errors or look in the log to find out the actually error

module config ViewJsonStrategy settings didn't work under child_route link

I don't know how can I explain my problem. I'm trying to get JSON response from one of my module that extend abstractrestfulcontroler. I have following module configuration
File: module.config.php
return array(
'controllers' => array(
'invokables' => array(
'TfwCommunication\\Controller\\TfwCommunication' => 'TfwCommunication\\Controller\\TfwCommunicationController',
'TfwCommunication\\Controller\\TfwChat' => 'TfwCommunication\\Controller\\TfwChatController',
'TfwCommunication\\Controller\\TfwContacts' => 'TfwCommunication\\Controller\\TfwContactsController',
'TfwCommunication\\Controller\\TfwMessage' => 'TfwCommunication\\Controller\\TfwMessageController',
'TfwCommunication\\Controller\\TfwUserMessageTemplates' => 'TfwCommunication\\Controller\\TfwUserMessageTemplatesController',
'TfwCommunicationControllerTfwUserMessageTemplates' => 'TfwCommunication\\Controller\\TfwUserMessageTemplatesController',
),
),
'router' => array(
'routes' => array(
'communication' => array(
'type' => 'Segment',
'options' => array(
'route' => '/communication',
'constraints' => array(
#'id' => '[0-9]+', # '[a-zA-Z][a-zA-Z0-9_-]*',
#'action'=>'[a-z][a-z0-9]*',
),
'defaults' => array(
'controller' => 'TfwCommunication\\Controller\\TfwCommunication',
'action' => 'index',
#'id'=>'update',
#'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'actions'=>array(
'type' => 'Segment',
'options' => array(
'route' => '/[:action[/]]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
'controller' => 'TfwCommunication\\Controller\\TfwCommunication',
'action' => 'index',
),
),
),
'message' => array(
'type' => 'Segment',
'options' => array(
'route' => '/message',
'defaults' => array(
'controller' => 'TfwCommunication\\Controller\\TfwMessage',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'read'=>array(
'type' => 'Segment',
'options' => array(
'route' => '/[:id]',
'constraints' => array(
'id' => '[0-9]*',
),
'defaults' => array(
'controller' => 'TfwCommunication\\Controller\\TfwMessage',
'action' => 'read',
),
),
),
'actions'=>array(
'type' => 'Segment',
'options' => array(
'route' => '/[:action[/[:id]]]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '.*',
),
'defaults' => array(
'controller' => 'TfwCommunication\\Controller\\TfwMessage',
'action' => 'index',
),
),
),
'json-request-by-child-route'=>array(
'type' => 'Segment',
'options' => array(
'route' => '/json-request-by-child-route[/:id]',
'constraints' => array(
'id' => '.*',
),
'defaults' => array(
'controller' => 'TfwCommunicationControllerTfwUserMessageTemplates',
),
),
),
),
),
),
),
'user-defined-templates'=>array(
'type' => 'Segment',
'options' => array(
'route' => '/communication/message/user-defined-templates[/:id]',
'constraints' => array(
'id' => '.*',
),
'defaults' => array(
'controller' => 'TfwCommunication\\Controller\\TfwUserMessageTemplates',
),
),
),
'user-defined-templates-direct-link'=>array(
'type' => 'Segment',
'options' => array(
'route' => '/user-defined-templates-direct-link[/:id]',
'constraints' => array(
'id' => '.*',
),
'defaults' => array(
'controller' => 'TfwCommunication\\Controller\\TfwUserMessageTemplates',
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'tfwcommunication' => __DIR__ . DS.'..'.DS.'view',
),
'strategies' => array(
'ViewJsonStrategy',
),
),
);
Now following link is working - tfw.com.bd/communication/message/user-defined-templates/ OR tfw.com.bd/user-defined-templates-direct-link/
But following link will not work as expected (it says 404 controller not found) - tfw.com.bd/communication/message/json-request-by-child-route
Here tfw.com.bd indicating localhost.
Please note, I'm expected output as JSON format.
Also noted that, all I use here same controller. In some link/route it didn't work. I can't figure out the reason.
Can any ZF2 expert here who can explain the real reason behind the behavior.
Thanks
Finally I got this answer by myself. The above routing configuration didn't works due to default "action" define as "index". Zend seek "action" parameter, if found then it load that action. If not found it return "notFoundAction". So, in child route of above router defines "action" parameter. So, Zend din't go further when either it goes default "indexAction" or goes "notFoundAction".
Footnote, you need to avoid action parameter to get "JsonStrategy" works as expected. If you can't avoid action parameter in your router you can fix it by overloading "onDispatch" method of "AbstractRestfulController" controller.
Here is my code that works for me -
public function onDispatch(MvcEvent $e){
$routeMatch = $e->getRouteMatch();
if (! $routeMatch) {
/**
* #todo Determine requirements for when route match is missing.
* Potentially allow pulling directly from request metadata?
*/
throw new Exception\DomainException(
'Missing route matches; unsure how to retrieve action');
}
$request = $e->getRequest();
// Was an "action" requested?
#die('get_class($routeMatch): '.get_class($routeMatch).' #'.__LINE__.': '.__FILE__);
$action = $routeMatch->getParam('action', false);
if ($action) {
// Handle arbitrary methods, ending in Action
$method = static::getMethodFromAction($action);
if (! method_exists($this, $method)) {
if($method=='indexAction'){
$routeMatch->setParam('action', false);
return parent::onDispatch($e);
}
$method = 'notFoundAction';
}
$return = $this->$method();
$e->setResult($return);
return $return;
}
return parent::onDispatch($e);
}

how to pass params using a route in Zend Framework 2?

i have a router test/view and i would like to pass some params like test/view/id/123.
Im not sure how to add those params in the zf2 router.
'router' => array(
'routes' => array(
'test' => array(
'type' => 'Literal',
'options' => array(
'route' => '/test',
'defaults' => array(
'__NAMESPACE__' => 'test\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'view' => array(
'type' => 'Literal',
'options' => array(
'route' => '/view',
'defaults' => array(
'controller' => 'Index',
'action' => 'view',
),
),
),
),
),
),
),
i setup view as a child route but not sure where to add those params.
i've tried 'route' => '/view/:id/:value' and
'defaults' => array(
'controller' => 'Index',
'action' => 'view',
'id' => 'value',
)
but they don't seem to work
i am trying to understand how all this works.
any ideas? thanks
'router' => array(
'routes' => array(
'test-view' => array(
'type' => 'segment',
'options' => array(
'route' => '/test/view/:testId[/]',
'constraints' => array(
'testId' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Test\Controller\Index',
'action' => 'view'
),
),
),
In your ControllerAction you can then get the parameter "testId" by using:
$this->params('testId');
Btw: The above route gives you an url like this: /test/view/123 - I thought you may get rid of the "id" param.
If you want to create a link to one kind of this pages, you can use $this->url('test-view', array('testId' => 123)) in one of your views.

Categories