CakePHP 2.x i18n route - cakephp

There is some solution for using CakePHP route with params only when are not empty?
Now I code below, but I would like some better:
if(Configure::read('Config.language') !== 'en') { // en is default language
$language = '/:language';
} else {
$language = '';
}
Router::connect($language .'/'. __('register', true), array(
'controller' => 'users',
'action' => 'register'));
This code works perfectly, but I still must set language in AppHelper by url() method.
In older apps I was always duplicate Router::connect:
Router::connect('/:language/'. __('register', true), array(
'controller' => 'users',
'action' => 'register')); // for all languages without default language
Router::connect('/'. __('register', true), array(
'controller' => 'users',
'action' => 'register')); // only for default language (en)
Maybe there is simplest solutions?

You need to use 2 routes but add the 'persist' option for your language based routes. Adding 'persist' will avoid having to specify 'language' key each time when generating urls.
// for all languages without default language.
Router::connect(
'/:lang/'. __('register', true),
array(
'controller' => 'users',
'action' => 'register'
),
array(
'persist' => array('lang')
)
);
// only for default language (en)
Router::connect(
'/'. __('register', true),
array(
'controller' => 'users',
'action' => 'register'
)
);
You might also want to checkout CakeDC's I18n plugin.

Ok, these things work better, but I still other problem.
I set default language by Configure::write('Config.language'); to en in bootstrap.php
Next i wrote shema for url like this:
Router::connect('/:language/'. __('register', true), array('controller' => 'users', 'action' => 'register'), array('persist' => array('lang')));
Router::connect('/'. __('register', true), array('controller' => 'users', 'action' => 'register'));
And when users change language by beforeFilter in AppController (set new Config.language) will content from static .po and db worsk perfeclty, but links not translated.
Parametr :language works but magic function __() in Router:connect() not works.
Because first loaded is bootstrap.php, next is router.php and last is AppController.php
My question is, how to force router.php to translate links (__())?
Sorry, but still learn english...

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: storing origin URL when redirecting to login page using Permit class

In Config/Permit.php we define rules, which actions are permitted without login. It looks like that:
Permit::access(
array(
'controller' => array('incentives'), 'action' => array('downloadvoucher')
),
array(),
array()
);
(...)
Permit::access(
array('controller' => $controllers),
array('auth' => true),
array('redirect' => array('controller' => 'users', 'action' => 'login'), 'message' => __('Your session has ended. Please log in again.'))
);
The redirect is defined at the bottom. What would be the right approach to achieve the following: if the user calls an URL (note: by default in the following format: base/controller/action/?q=1&q=2#hash or with routing) he will be redirected to the users/login page, but we would like to store somewhere from where he is coming (for example appended to the URL).
I tried this:
array('redirect' => array('controller' => 'users', 'action' => 'login', '?' => $this->here()), 'message' => __('Your session has ended. Please log in again.'))
but of course it doesn't work - the here()method is not defined in the Permit class.
Any better ideas?

CakePHP - How to make routes with custom parameters?

My Cake URL is like this:
$token = '9KJHF8k104ZX43';
$url = array(
'controller' => 'users',
'action' => 'password_reset',
'prefix' => 'admin',
'admin' => true,
$token
)
I would like this to route to a prettier URL like:
/admin/password-reset/9KJHF8k104ZX43
However, I would like the token at the end to be optional, so that in the event that someone doesn't provide a token it is still routed to:
/admin/password-reset
So that I can catch this case and redirect to another page or display a message.
I've read the book on routing a lot and I still don't feel like it explains the complex cases properly in a way that I fully understand, so I don't really know where to go with this. Something like:
Router::connect('/admin/password-reset/:token', array('controller' => 'users', 'action' => 'password_reset', 'prefix' => 'admin', 'admin' => true));
I don't really know how to optionally catch the token and pass it to the URL.
You'll want to use named parameters. For an example from one of my projects
Router::connect('/:type/:slug',
array('controller' => 'catalogs', 'action' => 'view'),
array(
'type' => '(type|compare)', // regex to match correct tokens
'slug' => '[a-z0-9-]+', // regex again to ensure a valid slug or 404
'pass' => array(
'slug', // I just want to pass through slug to my controller
)
));
Then, in my view I can make a link which will pass the slug through.
echo $this->Html->link('My Link', array('controller' => 'catalogs', 'action' => 'view', 'type' => $catalog['CatalogType']['slug'], 'slug' => $catalog['Catalog']['slug']));
My controller action looks like this,
public function view($slug) {
// etc
}

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

CakePHP use Regex variable capture in routes?

In my CakePHP app I have static pages set up like this:
Router::connect(
'/terms',
array('controller' => 'pages', 'action' => 'display', 'terms')
);
This will rewrite /terms to /pages/display/terms To make prettier shorter URLs.
Now If I wanted to do this for all my static pages, it would get quite redundant:
Router::connect(
'/terms',
array('controller' => 'pages', 'action' => 'display', 'terms')
);
Router::connect(
'/privacy',
array('controller' => 'pages', 'action' => 'display', 'privacy')
);
Router::connect(
'/about',
array('controller' => 'pages', 'action' => 'display', 'about')
);
With regular mod_rewrite you can do something like this:
/(terms|privacy|about) /pages/display/$1
So I naturally attempted this:
Router::connect(
'/(terms|privacy|about)',
array('controller' => 'pages', 'action' => 'display', '$1')
);
It does not work. Is there support for something like this, if so how do you do it?
Just off the top of my head, this may solve the issue. To perform a regex match on a portion you need to do so like this:
Router::connect(
'/:page',
array(
'controller' => 'pages',
'action' => 'display',
),
array(
'page' => '(terms|privacy|about)',
'pass' => array('page')
)
);
Notice how the page placeholder in the URL gets extrapolated on in the third parameter, the array. In there we say that it must match the provided regular expression. Also of note is that it also says to pass the page placeholder to the action method. That way it knows which page to render.

Resources