Phalcon route conflict - php

I have a problem with routes on phalcon. I have code:
$router->add('/{aliascat:[0-9\-a-z\-]+}(/?)', array(
'module' => 'frontend',
'controller' => 'category',
'action' => 'view',
'category' => 1,
'lang' => 'md',
))->setName('category_view_cpu');
$router->add('/{lang:[' . $langsDefined . ']{2}+}/{aliascat:[0-9\-a-z\-]+}(/?)', array(
'module' => 'frontend',
'controller' => 'category',
'action' => 'view',
'category' => 2,
'lang' => 1,
))->setName('category_view_cpu');
$router->add('/{controller:[a-z]{3,50}+}(/?)', array(
'module' => 'frontend',
'controller' => 1,
'action' => 'index',
'lang' => 'md',
))->setName('default_module');
$router->add('/{lang:[' . $langsDefined . ']{2}+}/{controller:[a-z]{3,50}+}(/?)', array(
'module' => 'frontend',
'controller' => 2,
'action' => 'index',
'lang' => 1,
))->setName('default_module_lang');
$router->add('/{controller:[a-z]{3,50}+}/:action/', array(
'module' => 'frontend',
'controller' => 1,
'action' => 2,
'lang' => 'md',
))->setName('default_module_controller_action');
$router->add('/{lang:[' . $langsDefined . ']{2}+}/{controller:[a-z]{3,50}+}/:action/', array(
'module' => 'frontend',
'controller' => 2,
'action' => 3,
'lang' => 1,
))->setName('default_module_controller_action_lang');
$router->add('/{controller:[a-z]{3,50}+}/:action/:params/', array(
'module' => 'frontend',
'controller' => 1,
'action' => 2,
'params' => 3,
'lang' => 'md',
))->setName('default_module_controller_action_params');
$router->add('/{lang:[' . $langsDefined . ']{2}+}/{controller:[a-z]{3,50}+}/:action/:params/', array(
'module' => 'frontend',
'controller' => 2,
'action' => 3,
'params' => 4,
'lang' => 1,
))->setName('default_module_controller_action_params_lang');
I get undifined controller for category route, because conflict with default_module route. How I can fix this problem?
I have route: /category-name/
And default: /controller/action/...
Conflict with routes.

Reading your code, I found several improvements that can be made:
1) First, you dont need two hyphens in those regexes. Instead of [0-9\-a-z\-], put [0-9a-z\-].
2) I see there are two repeated category_view_cpu names. Make sure to revise after you copy and paste. ;)
3) The logic for your routes are too broad and thus result in ambiguousness. For example, the routing definition and regex that you have for the category_view_cpu route (1st one) will behave very similar to the default_module route. So, in the 1st route, you are expecting an alphanumeric lowercase string (with optional hyphens), and in the default_module route you are also expecting a letters-only string with a minimum of 3 characters. So, if I type yoursite.com/dummy, the dummy
part will match the 1st route and also the default_module route. Phalcon doesnt have a way to know if dummy is either a controller or a category alias.
I do suggest that you don't make your routes so broad, by using route groups or by specifying controllers for certain routes that will only be handled for any given controller. For example:
$router->add('/categories/{alias:[0-9a-z\-]+}(/?)', array(
'module' => 'frontend',
'controller' => 'categories',
'action' => 'view',
'category' => 1,
'lang' => 'md',
))->setName('category_view_cpu');
Then, below this route ^, you can define the generic/default route that will catch all other requests. Example:
$router->add('/{controller:[a-z]{3,50}+}(/?)', array(
'module' => 'frontend',
'controller' => 1,
'action' => 'index',
'lang' => 'md',
))->setName('default_module');
What will happen with this example is that, if Phalcon gets a URL like /categories, it will match it with the first route that I made. But if it gets a route like: /dummy, then it will not match the first but will match my second route.
Route Groups are also great for helping distinguish and separate your routing logic. I suggest you read it entirely, here: https://docs.phalconphp.com/en/3.2/routing#defining-groups-of-routes

Related

Phalcon two single routes

I have a problem. I have two routes:
$router->add('/news/{alias:[a-z\-]+}(/?)', array(
'module' => 'frontend',
'controller' => 'news',
'action' => 'view',
'news_id' => 1,
'lang' => 'md',
))->setName('news_view_short_e'); //=> /news/282334-alias-news
AND route => /news/index/:
$router->add('/{lang:[' . $langsDefined . ']{2}+}/{controller:[a-z]{3,50}+}(/?)', array(
'module' => 'frontend',
'controller' => 2,
'action' => 'index',
'lang' => 1,
))->setName('default_module_lang');
When I use these routes. site.com/news/index not working. But if I remove route with alias. Route site.com/news/index working good. How I can resolve conflict?
Probably because it matches your "index" as alias parameter too, so first rule wins. There's no magic solution other than just fixing your regex or reordering your routes.
Reversing your routes order will bring a new problem though, reversely because it will also match the controller instead of your alias.
I prefer to stick with the default routing, and mount a router group here's my router right now:
//From my config
'router' => array(
'defaults' => array(
'namespace' => 'My\\Default\\Namespace\\Controllers',
'module' => 'frontend',
'controller' => 'index',
'action' => 'index'
),
'notFound' => array(
'controller' => 'errors',
'action' => 'notFound'
)
),
// From my service
$router = new Router();
$router->removeExtraSlashes(true);
$router->setDefaults($this->config->router->defaults->toArray()?: $this->defaults);
$router->notFound($this->config->router->notFound->toArray()?: $this->notFound);
$router->mount(new ModuleRoute($this->getDefaults(), true));
class ModuleRoute extends RouterGroup
{
public $default = false;
public function __construct($paths = null, $default = false)
{
$this->default = $default;
parent::__construct($paths);
}
public function initialize()
{
$path = $this->getPaths();
$routeKey = '/' . $path['module'];
$this->setPrefix('/{locale:([a-z]{2,3}([\_\-][[:alnum:]]{1,8})?)}' . ($this->default ? null : $routeKey));
$this->add( '/:params', array(
'namespace' => $path['namespace'],
'module' => $path['module'],
'controller' => $path['controller'],
'action' => $path['action'],
'params' => 3
))->setName($routeKey);
$this->add( '/:controller/:params', array(
'namespace' => $path['namespace'],
'module' => $path['module'],
'controller' => 3,
'action' => $path['action'],
'params' => 4
))->setName($routeKey);
$this->add( '/:controller/([a-zA-Z0-9\_\-]+)/:params', array(
'namespace' => $path['namespace'],
'module' => $path['module'],
'controller' => 3,
'action' => 4,
'params' => 5
))->setName($routeKey);
$this->add( '/:controller/:int', array(
'namespace' => $path['namespace'],
'module' => $path['module'],
'controller' => 3,
'id' => 4,
))->setName($routeKey);
}
}

Using Router Annotations with other routes in Phalcon

Is it possible to use annotations on top of regular routes in Phalcon. For example, I have this:
$router->add('/', [
'module' => 'home',
'controller' => 'index',
'action' => 'index'
])->setName('home');
$router->notFound([
'module' => 'home',
'namespace' => 'Home\Controller',
'controller' => 'error',
'action' => 'show404'
]);
foreach ($app->getModules() as $key => $module) {
$router->add('/'.$key.'/:params', [
'module' => $key,
'controller' => 'index',
'action' => 'index',
'params' => 1
])->setName($key);
$router->add('/'.$key.'/:controller/:params', [
'module' => $key,
'controller' => 1,
'action' => 'index',
'params' => 2
]);
$router->add('/'.$key.'/:controller/:action/:params', [
'module' => $key,
'controller' => 1,
'action' => 2,
'params' => 3
]);
}
$router->addModuleResource('api', 'Api\\Controller\\Index', '/api/index');
$router->addModuleResource('api', 'Api\\Controller\\Client', '/api/client');
The problem is that the router annotations that I define near the bottom don't seem to work, probably because the routes to /api/index and /api/client have already been defined above.
Also, at the same time, is there a way to define a notFound for a module? Basically, if I'm at some URL that starts with /api/, I would like it to go to an error page in my api module. Otherwise, it should go to error page in the regular module.

Using route in Zend Framework 2

i need to route urls like in zf1.
in particular i need that these urls will be automatically redirect to appropriate actions without specify a new route every time.
/site/getData
/site/getData?param=5&par2=test
/site/getOther
...
So a segment route doesn't work, i've tried a Literal route but i can't reach a working solutions.
Anyone can help me?
Thanks a lot
This should be solved by a pretty default segment route like the one provided in the documentation.
'type' => 'Zend\Mvc\Router\Http\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(
'controller' => 'default-controller-alias',
'action' => 'index',
),
)
Now if you set up your controller names like the following:
'controllers' => array(
'invokables' => array(
'sites' => 'Namespace\Controller\SitesController',
'other' => 'Namespace\Controller\OtherController'
Then you should be able to achieve exactly what you want. And to create params to your route, you simply use the ViewHelper correctly ;)
$this->url('routename',
array(
'controller' => 'site',
'action' => 'getData'
),
array (
'query' => array(
'param1' => 'foo',
'param2' => 'bar',
'paramN' => 'baz',
)
)
)

Zend Framework 2 Part Route Assembly

My Zend Framework 2 application has a route definition that's trying to mimic the default Zend Framework 1 route. It looks like:
'router' => array(
'routes' => array(
'default' => array(
'type' => 'segment',
'options' => array(
'route' => '/[:controller[/:action]]',
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'wildcard' => array(
'type' => 'wildcard',
),
),
),
),
),
It matches routes just fine, but I can't assemble routes with arbitrary parameters using the Url view helper.
For example,
$this->url('default', array('controller' => 'test', 'action' => 'test', 'id' => 5));
results in /test/test instead of /test/test/id/5.
Does anyone know how to assemble partial routes like this? Or is there a better way of getting ZF1-style routes?
It turns out that you need to specify the entire route name (including child routes) in the Url view helper.
Using the router defined in my question, the proper view helper call would look like:
$this->url('default/wildcard', array('controller' => 'test', 'action' => 'test', 'id' => 5));
which would result in a url of /test/test/id/5.

Zend_Controller_Router_Route

I'm trying to make a Router that can respond to this structure:
module/controller/action/id and module/controller/action/page
The only difference is is 'id' or 'page'. I'm using this code:
$routeAdmin = new Zend_Controller_Router_Route(
'administrador/:controller/:action/:id/:pg',
array(
'module' => 'administrador',
'controller' => 'index',
'action' => 'index',
'id' => 0,
'pg' => 1
),
array(
'id' => '\d+',
'pg' => '\d+'
)
);
$router->addRoute('administrador', $routeAdmin);
The problem is that in some situations i want:
'http://www.domain.cl/administrador/productos/2' => (module=>administrador, controller=>productos,page=>2) but with the router 'administrador' result in 'http://www.domain.cl/administrador/productos/index/0/2' (module=>administrador, controller=>productos,action=>index,id=>0,page=>2)
I'm very confused about how it works for cases like this. I tried to make two router where the first only have 'id' param and the other 'page' param. And from url helper use it like:
$this->url(array('module' => 'administrador', 'controller' => 'productos', 'action' => 'index', 'id' => 0), 'administradorId');
$this->url(array('module' => 'administrador', 'controller' => 'productos', 'action' => 'index', 'page' => 1), 'administradorPg');
But when I used the routers always select the last one added to the router ($router->addRoute('routerIdentifier', $route);)
Thanks
I have had a similar issue and I got around this by defining just one route like this
$routeAdmin = new Zend_Controller_Router_Route(
'administrador/:controller/:action/:id/:pg',
array(
'module' => 'administrador',
'controller' => 'index',
'action' => 'index',
'id' => 0
),
array(
'id' => '\d+'
)
);
$router->addRoute('administrador', $routeAdmin);
In your actions you'd then need to get the id and check for it somewhere where that id might be, for example if you were in /administrador/events/view/1 then you might look in the events table or if you were in /administrador/pages/view/1 then you would look for a page.
But the problems really start when the id could be either an event or a page in a given controller and action. The only real way around this is explicitly set the type of id your using for example
/administrador/events/view/index/id/1
or
/administrador/pages/view/index/page/1
If you want to remove the index part then set up routes like
$routeAdmin = new Zend_Controller_Router_Route(
// Remove the action from here and explicitly set the controller
'administrador/pages/:pg',
array(
'module' => 'administrador',
'controller' => 'pages',
// Then set the default action here
'action' => 'index',
'pg' => 0
),
array(
'pg' => '\d+'
)
);
$router->addRoute('administradorpages', $routeAdmin);
What your asking for basically results in a lot of guess work and therefore risk of producing unexpected results.
Have a look at dynamic segments in routes. It is not exactly what you want, but it might be helpful in your case.

Categories