CakePHP 3.* Prefix routing error - cakephp

I made 3 tables namely Roles, Users, and Blogs. Roles have a 1 to many relationship with Users having a role_id foreign key, and likewise, Users have a one to many relationship with Blogs having the user_id foreign key. I initially baked all 3 users and everything was fine. I then decided to try prefixing admin for Roles.
Router::prefix('admin', function ($routes) {
$routes->connect('/roles', ['controller' => 'Roles', 'action' => 'index]
)};
I made a folder inside the Controller folder (Controller > Admin) and put my RolesController there. I changed the namespace of my RolesController to namespace App\Controller\Admin. I also adjusted the file location of my Roles View files by putting it inside an Admin Folder (Admin > Roles > add.ctp, edit.ctp, index.ctp, view.ctp).
Everytime I try to access localhost:8765/admin/roles, I get an error message that says:
Error: A route matching "array ( 'action' => 'add', 'prefix' => 'admin', 'plugin' => NULL, 'controller' => 'Roles', '_ext' => NULL, )" could not be found. None of the currently connected routes match the provided parameters. Add a matching route to config/routes.php
The passed context was:
[
'_base' => '',
'_port' => (int) 8765,
'_scheme' => 'http',
'_host' => 'localhost',
'params' => [
'pass' => [],
'controller' => 'Roles',
'action' => 'index',
'prefix' => 'admin',
'plugin' => null,
'_matchedRoute' => '/admin/roles',
'_ext' => null
]
I am fairly new to cakephp, could someone please help me with this problem? Any advise would be much appreciated.

By adding $routes->connect('/roles', ['controller' => 'Roles', 'action' => 'index] you're only routing /admin/roles (index action) but not any other action of Roles.
If you only plan of having Roles in Admin then you should only add this line in your Router::prefix block:
$routes->connect('/roles/:action/*', ['controller' => 'Roles']);
Otherwise you should add a default fallback (as the / scope has) by adding this line: (note that it can be the only line in the Router::prefix block):
$routes->fallbacks(DashedRoute::class);
Your block will then look like that:
Router::prefix('admin', function ($routes) {
$routes->fallbacks(DashedRoute::class);
)};
See https://book.cakephp.org/3.0/en/development/routing.html#fallbacks-method for more informations about fallbacks methods in CakePHP.

Related

CakePHP 3 use default routing in some cases

I have a CakePHP 3.5 website. It was necessary to set slugs without any url prefixes like /pages/slug, so I wrote the following rule:
$routes->connect(
'/:slug',
['controller' => 'Pages', 'action' => 'redirectPage']
)
->setMethods(['GET', 'POST'])
->setPass(['slug'])
->setPatterns([
'slug' => '[a-z0-9\-_]+'
]);
It works nice, but in some cases I want cakePHP to route as default (Controller/Action/Params). For example, I want /admin/login to call 'login' action in 'AdminController'.
I have two ideas that doesn't need exact routings, but I can't make any of them to work:
Filtering some strings by pattern: It would be nice if I could filter some strings, that if slug doesn't match pattern, it will simply skip the routing rule.
Create a '/admin/:action' routing rule, but then I cant use :action as an action variable. It causes errors.
$routes->connect(
'/admin/:action',
['controller' => 'Admin', 'action' => ':action']
)
Any ideas?
Thanks
You can use prefix for admin restricted area.
Example:
Router::prefix('admin', function ($routes) {
$routes->connect('/', ['controller' => 'Users', 'action' => 'login']);
$routes->fallbacks(DashedRoute::class);
});
$routes->connect('/:slug' , [
'controller' => 'Pages',
'action' => 'display',
'plugin' => NULL
], [
'slug' => '[A-Za-z0-9/-]+',
'pass' => ['slug']
]);
Now, for example, path /admin/dashboard/index will execute method in Admin "subnamespace" \App\Controller\Admin\DashboardController::index()
Its nicely described in docs: https://book.cakephp.org/3.0/en/development/routing.html#prefix-routing
Try this:
$routes->connect(
'/admin/:action',
['controller' => 'Admin'],
['action' => '(login|otherAllowedAction|someOtherAllowedAction)']
);
Also, your slug routes seems to not catch /admin/:action routes, b/c dash is not allowed there: [a-z0-9\-_]+

CakePHP Routing with slug and language

I need route containing Both language parameter and slug in the url.
i.e http://localhost/demo/eng/home
Here "eng" is language name and "home" is slug name.
I have done following code in route.php
Router::connect('/:language/:action/*',array('controller' => 'homes'),array('language' => '[a-z]{3}'));
Router::connect('/:language/:slug/*', array('controller' => 'homes', 'action' => 'view'), array('language' => '[a-z]{3}','slug' => '[a-zA-Z0-9_-]+'));
Router::connect('/:slug',array('controller' => 'homes','action' => 'view'),array('slug' => '[a-zA-Z0-9_-]+'));
Also in view
You have conflicted routes.
I am guessing that you are trying to pass a URL array like the following to HtmlHelper::link() or HtmlHelper::url():
[
'controller' => 'homes',
'action' => 'view',
'language' => 'eng',
'slug' => 'press-release',
]
But this array matches not only /:language/:slug/* but also /:language/:action/*. Because both language and action are contained, and slug matches * as a named parameter.
And /:language/:action/* appears before /:language/:slug/* in your routes.php. If you define conflicted routes, the first defined route has higher priority. Thus, you get the URL /eng/view/slug:press-release.
In conclusion, /:language/:action/* should be removed or should be defined at least after /:language:/:slug/*.

Cakephp admin url routing not working

I have developed a large website in CakePHP. On development time my admin URL was SITE_URL/admin. Now my client wants it with lc_admin. So I change prefixes in core.php file but when I tried to access any page it shows me error that lc_admin_index() action is not defined. Because my actions are with admin_index and so on.
To solve this issue I tried code below
Router::connect('/lc_admin/:controller', array('action' => 'index', 'prefix' => 'admin', 'admin' => true));
Router::connect('/lc_admin/:controller/:action/*', array('prefix' => 'admin', 'admin' => true));`
But with this my old URL called SITE_URL/admin also working. And I want new URL accessible.
if you want direct route path by keyword then use simple.
Route path
Router::connect('/lc_admin',array('controller' => 'admin', 'action' => 'index'));
you should give the prefix the same value, as you have in your url, please try this:
Router::connect('/lc_admin/:controller', array('prefix' => 'lc_admin', 'admin' => true));
Router::connect('/lc_admin/:controller/:action', array('prefix' => 'lc_admin', 'admin' => true));
Router::connect('/lc_admin/:controller/:action/*', array('prefix' => 'lc_admin', 'admin' => true));
also, please note, that all your actions (that are called with this url pattern) should have prefix admin_ or you should change it accordingly.

Weird redirect issue when using Auth and admin prefix in CakePHP

I'm using the admin prefix in my Cakephp app, for some admin views. I'm also using Auth to restrict access to those views, based on a role field in the User table. Pretty standard.
The problem is, that when an unauthorized user tries to go to, say, admin/users, (in this case the index action is prohibited), they are redirected to /admin/users/login which of course, doesn't exist.
This doesn't happen with actions that do not have the admin prefix. Those behave just fine.
Why are users being sent to to a login that is prepended by the admin prefix and the prohibited action?
Anyone who is still having trouble with this, according to the documentation you can use an array or a string in loginAction (Documentation).
Using an array and setting 'admin' => false was still giving me trouble, so I tried using a string instead:
public $components = array(
'Auth' => array(
'loginRedirect' => array('controller' => 'dashboards', 'action' => 'home'),
'logoutRedirect' => array('controller' => 'users', 'action' => 'login'),
'loginAction' => '/users/login',
'authorize' => array('Actions')
),
);
This ended up solving my problem. Hopefully it works for you as well.
You need to override the specific prefix in the routing array.
$this->Auth->loginAction = array(
'controller' => 'users',
'action' => 'login',
'admin' => false
);
or, if you're using multiple prefixes, you can dynamically remove the prefix name like this:
$this->Auth->loginAction = array(
'controller' => 'users',
'action' => 'login',
$this->request->prefix => false
);

Routing: 'admin' => true vs 'prefix' => 'admin in CakePHP

Hi I'm setting up admin routing in CakePHP.
This is my current route:
Router::connect('/admin/:controller/:action/*', array('admin' => true, 'prefix' => 'admin', 'controller' => 'pages', 'action' => 'display', 'home'));
It works fine, but I don't understand what the difference between 'admin' => true, and 'prefix' => 'admin' is.
When I omitted 'prefix' => 'admin', the router wouldn't use admin_index and would instead just use index. So what's the point of 'admin' => true?
By setting 'prefix' => 'admin' you are telling CakePHP that you want to use a prefix of admin for that route; basically meaning you want to use controller actions and views that have names prefixed with admin_. This part you are already aware of, and things will probably work fine with just this.
When creating routes though, any array keys passed into the second argument that aren't recognised by CakePHP (ie. not your usual controller, action, plugin, prefix stuff) are set as named parameters during requests matching that route.
Adding 'admin' => true is therefore just a named parameter in this case, but it comes with its advantages. Firstly, it can make code more succinct.
/* Determine if a request came through admin routing */
// without:
if ($this->params['prefix'] == 'admin') {}
// with:
if ($this->params['admin']) {}
/* Create a link that is reverse-routed to an admin prefixed route */
// without:
$html->link('...', array('prefix' => 'admin', 'controller' => 'users'));
// with:
$html->link('...', array('admin' => true, 'controller' => 'users'));
Secondly, it provides backwards compatibility with the way admin routing worked in CakePHP 1.2 (the last line from the above example is how you would have made admin routing links in 1.2). Therefore, developers migrating from 1.2 to 1.3 can prevent having to change links throughout their application by keeping the 'admin' => true flag in their routes (and adding the 'prefix' => 'admin' one).
Lastly, by setting a custom flag like this with a named parameter and using it in your application instead of referencing your route by an exact string means that you prevent yourself from ever having to change links if you change the prefix to something else (say from admin to administrator or edit)... although this is sort of a moot point, as you would need to rename all your admin_* controller actions and views. :)
// Go into a prefixed route.
echo $html->link('Manage posts', array('manager' => true, 'controller' => 'posts', 'action' => 'add'));
// leave a prefix
echo $html->link('View Post', array('manager' => false, 'controller' => 'posts', 'action' => 'view', 5));

Resources