Help with routing settings, there is the following request template with frontend: /books/([0-9]+)/book-authors/([0-9]+)/images
There is a controller located in namespace: Shop\Controllers\Books\BookAuthors\ImagesController
The controller has an indexAction method.
In routing.php I specify the following:
$router = new Router(false);
$router->removeExtraSlashes(true);
$router->setDefaultNamespace('Shop\Controllers');
$router->setDefaultController('index');
$router->setDefaultAction('index');
$router->addGet('/books/([0-9]+)/book-authors/([0-9]+)/images', [
'namespace' => 'Shop\Controllers\Books\BookAuthors',
'bookId' => 1,
'authorId' => 2,
'controller' => 'images',
'action' => 'index',
]);
return $router;
As a result, we get that the redirect always goes to the default controller. Please tell me how to fix...
I tried to debug and check why the template does not fit, but when I checked regex101 on the site, everything matches there and should work, but for some reason it does not work in phalcon.
Application return every time "not found"
The route works fine, although you can try this for simplicity and clarity:
$router->addGet('/books/{bookId:[0-9]+}/book-authors/{authorId:[0-9]+}/images',
[
'controller' => 'images',
'action' => 'index'
]
);
And in your ImagesController define indexAction as:
public function indexAction(int $bookId, int $authorId)
{
echo "BookId: $bookId and AuthorId: $authorId";
}
For /books/10/book-authors/22/images the result should be:
BookId: 10 and AuthorId: 22
Try this:
$router->addGet('/books/:int/book-authors/:int/images', [
'namespace' => 'Shop\Controllers\Books\BookAuthors',
'controller' => 'images',
'action' => 'index',
'bookId' => 1,
'authorId' => 2,
]);
Note that I don't know if you can have multiple ":int" in the router definition and I have not tried this code.
If you can't have multiple ":int" in the line, you may need to restructure and move the bookId and authorId to the end and use :params. Note that I also dropped the "images" controller name since you don't need that in the line.
$router->addGet('/books/book-authors/:params', [
'namespace' => 'Shop\Controllers\Books\BookAuthors',
'controller' => 'images',
'action' => 'index',
'params' => 1,
]);
Your URL would be something along the lines of "/books/book-authors/98/212" for bookID 98 and authorId 212.
Related
I don't know if someone else is using kohana (koseven with new name) framework for develepment. I need help about routing. I am migrating an asp site to php with using koseven ( kohana) framework and I must keep all the url routing on current site. Because of this I must use more than one routing on my project.
Url structer must be like this:
domain.com/contenttype/contentid -> contenttype is dynamic and gets data over Content Controller
domain.com/profile/username ->profile is the controller and index is the action. I must get the user name from id parameter.
domain.com/categories/categorname (Works fine-> categories is the controller, index is the action and categorname is the id parameter.
There is an admin page on my site and using a directory route on it.
Here is my route on bootstrap.php file:
Route::set('panel', '<directory>(/<controller>(/<action>(/<id>)))', array('directory' => 'panel'))
->defaults(array(
'controller' => 'panel',
'action' => 'index',
));
Route::set('kategori','<kategori>(/<id>)', array('id'=>'.*'))
->defaults([
'controller'=>'kategori',
'action'=>'index',
]);
Route::set('default', '(<controller>(/<action>(/<id>)))', array('id'=>'.*'))
->defaults([
'controller' => 'anasayfa',
'action' => 'index',
]);
First Problem: If I copy kategori route for profile it uses kategori route instead of profile.
Second Problem: How can I get dynamic routing for the contenttype. Content controller is the default controller and it will list the contents under the dynamic contenttype if there isn't given any content title on the id parameter. If the id parameter is identified at this time it will Show the detail of content.
Thanks.
Route::set('panel', 'panel(/<controller>(/<action>(/<id>)))', ['controller' => '\w+', 'action' => '\w+', 'id' => '[-\w]+'])
->defaults(array(
'directory' => 'panel',
'controller' => 'dashboard',
'action' => 'index',
'id' => null,
));
Route::set('kategori','<kategori>(/<id>)', ['kategori' => '[-\w]+', 'id' => '[-\w]+'])
->defaults([
'controller' => 'kategori',
'action' => 'index',
'id' => null,
])
->filter(function ($route, $params, $request) {
$model = ORM::factory('Kategori', ['kategori' => $params['kategori'], 'id' => $params['id']]);
if ($model->loaded()) {
$params['model'] = $model;
return $params;
}
return false;
});
Route::set('default', '(<controller>(/<action>(/<id>)))', ['controller' => '\w+', 'action' => '\w+', 'id' => '[-\w]+'])
->defaults([
'controller' => 'anasayfa',
'action' => 'index',
'id' => null,
]);
I am writting an application with zf2 and I came to this issue which I don't know how to implement.
At the moment I have a router like this :
'routes' => [
'stock' => [
'type' => 'regex',
'options' => [
'regex' => '/stock(?<sku>\/.*)',
'defaults' => [
'controller' => MyController::class,
'action' => 'check',
],
'spec' => '/path%path%'
],
So when my url contains ../stock/13567/2312 the parameter gets passed into the checkAction function.
However, I would like to show a different content when the url is just ../stock/ or ../stock without any parameter sent. How can I achieve this ?
Thanks.
If you want to show different content depending if sku parameter is passed you can do following thing in your controller:
public function indexAction()
{
// Return sku parameter if exists, false otherwise
$sku = $this->params('sku', false);
if ($sku) {
// For example get single item
...
$view->setTemplate('template-a');
} else {
// Get all items
...
$view->setTemplate('template-b');
}
return $view;
}
Just augment the regex to mark the param as optional, as in the docs:
'regex' => '/stock(?<sku>\/.*)?'
... and don't forget to provide the explicit default value:
'defaults' => [
'controller' => MyController::class,
'action' => 'check',
'sku' => '' // or else
],
My phalcon app has worked fine with standard MVC route convention.
However, I want to handle some variable via URL, then I have a route:
$router = new \Phalcon\Mvc\Router();
$router->add("/timesheet/some/{year:[0-9]+}/{month:[0-9]{2}}/{day:[0-9]{2}}", "Timesheet::some");
$router->add("/timesheet/getreport/{type:[a-z]}/{year:[0-9]+}/{month:[0-9]{2}}/{day:[0-9]{2}}", "Timesheet::getreport");
$router->addPost("/user/auth", "User::auth");
return $router;
The first route (timesheet/some) worked fine, I can access to "year", "month" variable using $year = $this->dispatcher->getParam("year");, however the second route (timesheet/getreport) doesn't work. In this case, $year = $this->dispatcher->getParam("year"); return null.
If I changed to
$router = new \Phalcon\Mvc\Router(false);
$router->add("/:controller/:action", array(
"controller" => 1,
"action" => 2,
));
$router->add("/timesheet/some/{year:[0-9]+}/{month:[0-9]{2}}/{day:[0-9]{2}}", "Timesheet::some");
$router->addPost("/timesheet/getreport/{type:[a-z]}/{year:[0-9]+}/{month:[0-9]{2}}/{day:[0-9]{2}}", "Timesheet::getreport");
$router->addPost("/user/auth", "User::auth");
return $router;
every request will be routed to index/index. My project URL is localhost/fpas, and I already try both route /fpas/timesheet/some and /timesheet/some but it always redirect to index/index. What's wrong with it? (security/auth is commented out, so it's not result from authentication).
From my understand, the default route, $router = new \Phalcon\Mvc\Router(); only allow you to follow MVC convention, while $router = new \Phalcon\Mvc\Router(false); do but you have to specific all routes for every controller/action. Can I keep the convention for most of the action, while have specific rewrite routes for some action. How can I do that?
Thank you very much.
It works for me:
$router = new Phalcon\Mvc\Router();
$router->add("/", array(
'controller' => 'index',
'action' => 'setLanguage',
));
$router->add("/{language:[a-z]{2}}", array(
'controller' => 'index',
'action' => 'index',
'language' => 1
));
this one get's default routing just with language in the beginning
$router->add("/{language:[a-z]{2}}/:controller/:action", array(
'controller' => 2,
'action' => 3,
'language' => 1
));
with default action "index" when it's not in url
$router->add("/{language:[a-z]{2}}/:controller", array(
'controller' => 2,
'action' => 'index',
'language' => 1
));
some other routes
$router->add("/{language:[a-z]{2}}/:controller/:action/:params", array(
'controller' => 2,
'action' => 3,
'language' => 1,
'params' => 4
));
$router->add("/{language:[a-z]{2}}/question/add/{type}", array(
'language' => 1,
'controller' => 'question',
'action' => 'add',
));
I'm developing a website using the PHP Phalcon Framework and I am really stuck in a problem with the router, here I go.
In order to restrict the HTTP Method for your route to match, I use this declaration:
$router->addGet('/admin/paginas', array(
'namespace' => 'Backend\Controllers',
'controller' => 'pagina',
'action' => 'list'
));
But it fails with the following error:
Unexpected value type: expected object implementing Phalcon\DiInterface, null given
I have some other routes defined in the same services.php file with add and there's no problem with them, for example:
$router->add('/oportunidades-trabajo', array(
'controller' => 'page',
'action' => 'oportunidadesTrabajo'
));
Works perfectly fine. I've tried removing namespace, changing the controller, using short sintax, using ->via() instead of addGet, but nothing solves my issue.
If i remove this route declaration everything works fine.
Here's the full declaration of the router:
$di->set('router', function () {
$router = new Router(false);
$router->removeExtraSlashes(true);
# FRONT END
$router->add('/oportunidades-trabajo', array(
'controller' => 'page',
'action' => 'oportunidadesTrabajo'
));
# BACK END - Paginas
# list
$router->addGet('/admin/paginas', array(
'namespace' => 'Backend\Controllers',
'controller' => 'pagina',
'action' => 'list'
));
# NOT FOUND
$router->notFound(array(
'controller' => 'page',
'action' => 'page404'
));
$router->handle();
return $router;
});
I would appreciate a lot your help, as I'm stuck with this and I cannot continue with the project.
Thanks a lot in advance for your time.
$router->handle(); must not be called in the service definition.
Just delete $router->handle();
Source: http://forum.phalconphp.com/discussion/3623/strange-error-with-the-phalcon-router
I have a controller setup to accept two vars: /clients/view/var1/var2
And I want to show it as /var1/var2
SO i tried
Router::connect('/*', array('admin'=>false, 'controller' => 'clients', 'action' => 'view'));
But this stops all other controllers working as /* routes everything
All other pages that are on the site are within the admin prefix so basically i need a route that is ignored if the current prefix is admin! I tried this (regex is from Regular expression to match a line that doesn't contain a word?):
Router::connect('/:one', array('admin'=>false, 'controller' => 'clients', 'action' => 'view'), array(
'one' => '^((?!admin).*)$'
));
But I think the regex is incorrect because if i naviate to /test it asks for the tests controller, not clients
My only other routes are:
Router::connect('/admin', array('admin'=>true, 'controller' => 'clients', 'action' => 'index'));
Router::connect('/', array('admin'=>false, 'controller' => 'users', 'action' => 'login'));
What am I doing wrong? Thanks.
I misunderstood your question the first time. I tested your code and didn't get the expected result either. The reason might be that the regex parser doesn't support negative lookahead assertion. But I still think you can solve this with reordering the routes:
The CakeBook describes which routes are automatically generated if you use prefix routing. In your case these routes have to be assigned manually before the '/*'-route to catch all admin actions. Here is the code that worked for me:
// the previously defined routes
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
Router::connect('/admin', array('controller' => 'clients', 'action' => 'index', 'admin' => true));
// prefix routing default routes with admin prefix
Router::connect("/admin/:controller", array('action' => 'index', 'prefix' => 'admin', 'admin' => true));
Router::connect("/admin/:controller/:action/*", array('prefix' => 'admin', 'admin' => true));
// the 'handle all the rest' route, without regex
Router::connect(
'/*',
array('admin'=>false, 'controller' => 'clients', 'action' => 'view'),
array()
);
Now I get all my admin controller actions with the admin prefix and /test1/test2 gets redirected to the client controller.
I think the solution is described in the bakery article on routing - "Passing parameters to the action" (code not tested):
Router::connect(
'/clients/view/:var1/:var2/*',
array(
'controller' => 'clients',
'action' => 'view'
),
array(
'pass' => array(
'var1',
'var2'
)
)
);
The controller action would look like:
public function view($var1 = null, $var2 = null) {
// do controller stuff
}
Also you have too look at the order of your routes (read section "The order of the routes matters"). In your example the '/*' stops all other routes if it comes first, if you assign the rule after the others it handles only requests which didn't match any other route.