I was struggling with a Placeholder for the Controller, what I wanted to achieve is to define the controller in the URL like this:
PHP Code:
$routes->get('{locale}/(:segment)', '$1::index');
This doesn't work because of the Router, which replaces the Placeholder with preg_replace and the backslash of the generated Namespace tells it, to ignore the next special character:
input:
\App\Controllers\$1::index
output:
\App\Controllers$1::index
To solve the problem, i did rewrite a small piece of code in the Router.php, line 467:
Old code:
PHP Code:
if (strpos($val, '$') !== false && strpos($key, '(') !== false && strpos($key, '/') !== false) {
$replacekey = str_replace('/(.*)', '', $key);
$val = preg_replace('#^' . $key . '$#', $val, $uri);
$val = str_replace($replacekey, str_replace('/', '\\', $replacekey), $val);
} elseif (strpos($val, '$') !== false && strpos($key, '(') !== false) {
$val = preg_replace('#^' . $key . '$#', $val, $uri);
} elseif (strpos($val, '/') !== false) {
[
$controller,
$method,
] = explode('::', $val);
// Only replace slashes in the controller, not in the method.
$controller = str_replace('/', '\\', $controller);
$val = $controller . '::' . $method;
}
New code:
PHP Code:
if (strpos($val, '$') !== false && strpos($key, '(') !== false) {
// Tell preg_replace to consider the backslash as a literal character.
$val = str_replace('\\', '\\\\', $val);
$val = preg_replace('#^' . $key . '$#', $val, $uri);
if (strpos($key, '/') !== false) {
$replacekey = str_replace('/(.*)', '', $key);
$val = str_replace($replacekey, str_replace('/', '\\', $replacekey), $val);
}
}
// Replace slashes in the controller with backslashes and capitalize the first letter.
[$controller, $method,] = explode('::', $val);
$controller = str_replace('/', '\\', $controller);
$controller = ucwords($controller, '\\');
$val = $controller . '::' . $method;
In addition to dynamic controllers it's also possible to nest the controllers inside the Namespace.
Following routes are working:
PHP Code:
$routes->get('{locale}/(:segment)', '$1::index');
$routes->get('{locale}/(:segment)', 'Home/$1::index');
It would be nice to add this or something similar to the official version.