Routing: 'admin' => true vs 'prefix' => 'admin in CakePHP - 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));

Related

CakePHP 3.* Prefix routing error

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.

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.

How to redefine the URLs generation without changes at the HtmlHelper#link(...) calls in CakePHP?

I have a CakePHP website with many internal links, that are build with the HtmlHelper:
/app/View/MyController/myaction.ctp
<?php
echo $this->Html->link(
$item['Search']['name'],
array(
'controller' => 'targetcontroller',
'action' => 'targetaction',
$profileId,
$languageId
)
);
?>
It works fine with the default route:
/app/Config/routes.php
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
The generated links look like that: /mycontroller/myaction/$profileId/$languageId.
Now I want to use search engine friendly URLs (with profile names and ISO-639-1 language codes instead of IDs) for a part of the website and added a new Route:
/app/Config/routes.php
Router::connect(
'/:iso6391/:name.html',
array('controller' => 'mycontroller', 'action' => 'myaction'),
array(
'iso6391' => '[a-zA-Z]+',
'name' => '[0-9a-zA-ZäöüßÄÖÜ\-]+',
)
);
And it also works fine and the incomming URIs like /producer/en/TestName.html are interpreted correctly.
But the HtmlHelper is still generating the old URIs like /mycontroller/myaction/1/1.
The docu says:
Reverse routing is a feature in CakePHP that is used to allow you to easily change your URL structure without having to modify all your code. By using routing arrays to define your URLs, you can later configure routes and the generated URLs will automatically update.
Well, the HtmlHelper gets a routing array as input, that means: I'm using the reverse routing.
Why does it not work? How to make the HtmlHelper generate the new URLs (without changing the HtmlHelper#link(...) calls)?
Bit of explanation first
You are technically not using reverse routing. You see, the output link, /mycontroller/myaction/1/1 definitively doesn't match /iso/name.html. Like, in no way. So, the routing skips that rule because it doesn't apply.
Code
Try this
echo $this->Html->link(
$item['Search']['name'],
array(
'controller' => 'targetcontroller',
'action' => 'targetaction',
'iso6391' => $someStringWithIso,
'name' => $someName
)
);
But for that, you have to change your routing a bit, because you are not passing the parameters (check the docs for examples)
Router::connect(
'/:iso6391/:name.html',
array('controller' => 'mycontroller', 'action' => 'myaction'),
array(
'pass' => array('iso6391', 'name'),
'iso6391' => '[a-zA-Z]+',
'name' => '[0-9a-zA-ZäöüßÄÖÜ\-]+',
)
);
And you have to mind the first string match /:iso6391/:name.html. Do you want to match this route to every controller and action in your project, or just the one controller and the one view. If it is for all projects, just for precaution, use this
/:controller/:action/:iso6391/:name.html
if is just for, say, Controller1 and action "view", use
/controller1/view/:iso6391/:name.html
The detail you need to consider is the extension you use .html, is that really necessary in the url? If it is, add it as a parameter in the Html#link
echo $this->Html->link(
$item['Search']['name'],
array(
'controller' => 'targetcontroller',
'action' => 'targetaction',
'iso6391' => $someStringWithIso,
'name' => $someName
'ext' => 'html'
)
);
and also add parseExtensions to the routing file. Read this. Would be easier if you don't add the extension, but that's up to you.
In the end, you still have to change your calls to Html->link...

CAKEPHP - how to leave the plug in url

I have a ACL plugin, and I want to be able to redirect back to users/index from this plug in.. but I end up getting funny url's that don't exist. such as /cakephp/admin/acl/users/index
how can I make it go to cakephp/users/index
I have looked through the HTML helper and I'm stumped.
I will be in the cakephp chat room as well
Thanks
You can 'reset' the plugin by setting it to 'false' when creating a link;
e.g.;
echo $this->Html->link('go to user overview', array(
'controller' => 'users',
'action' => 'index',
'plugin' => false
);
update
My guess is that you're using both prefix routing and a plugin. To reset both the plugin and the prefix, do this;
echo $this->Html->link('go to user overview', array(
'controller' => 'users',
'action' => 'index',
'plugin' => false, // resets the plugin
'admin' => false, // resets the admin-prefix
);

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
);

Resources