Helper function for making multilingual urls on CodeIgniter 4
This can be useful when you have Named Routes for multiple languages. In general, you want to use the same route name for different languages, but to do this we have to prefix the language. Let's see how.
Table of contents
Writing the helper function route()
Let's create the file app/Helpers/route_helper.php:
// app/Helpers/route_helper.php
use CodeIgniter\Router\Exceptions\RouterException;
if (!function_exists('route')) {
function route(string $routeName, ...$params) {
$locale = service('request')->getLocale();
$routes = service('routes');
if (strpos($routeName, '{locale}') !== false) {
$routeName = strtr($routeName, ['{locale}' => $locale]);
} else {
$routeName = $locale . '.' . $routeName;
}
$reverseRoute = $routes->reverseRoute($routeName, ...$params);
if (!$reverseRoute) {
throw RouterException::forInvalidRoute($routeName);
}
return $reverseRoute;
}
}
If we use a route name like {locale}.posts.index or even just posts.index we will obtain the link to the named route, if it is configured in our routes list of course.
Registering the helper
Then we add the new helper in our BaseController.php:
// app/Controllers/BaseController.php
// other code...
protected $helpers = [
// other helpers...
'route'
];
// other code...
Setting the multilingual routes
The following is just an example of how you could set up your routes:
// app/Config/development/Routes.php
# English
$routes->group('en', function() use ($routes) {
$routes->get('/', [HomeController::class, 'index'], ['as' => 'en.home']);
$routes->get('posts', [PostController::class, 'index'], ['as' => 'en.posts.index']);
$routes->get('posts/new', [PostController::class, 'new'], ['as' => 'en.posts.new']);
$routes->get('posts/(:num)', [PostController::class, 'show/$1'], ['as' => 'en.posts.show']);
$routes->post('posts/create', [PostController::class, 'create'], ['as' => 'en.posts.create']);
});
# Italian
$routes->group('it', function() use ($routes) {
$routes->get('/', [HomeController::class, 'index'], ['as' => 'it.home']);
$routes->get('annunci', [PostController::class, 'index'], ['as' => 'it.posts.index']);
$routes->get('annunci/nuovo', [PostController::class, 'new'], ['as' => 'it.posts.new']);
$routes->get('annunci/(:num)', [PostController::class, 'show/$1'], ['as' => 'it.posts.show']);
$routes->post('annunci/crea', [PostController::class, 'create'], ['as' => 'it.posts.create']);
});
Creating the link to the named route in our views
Now we can create the link in the views:
// app/Views/Login/form.php
// We could make a form like this:
<?= form_open_multipart(route('login')) ?>
...
<?= form_close() ?>
// And links like this:
// app/Views/layouts/base.php
<ul class="navbar">
<li>
<a href="<?= route('home') ?>">Homepage</a>
</li>
<li>
<a href="<?= route('posts.index') ?>">All posts</a>
</li>
<li>
<a href="<?= route('posts.new') ?>">New post</a>
</li>
</ul>
This way we can replicate on CodeIgniter 4 the same behaviour that Laravel offers with its own route() function.
Passing parameters to the route function
Since we added the possibility to have parameters, we can easily pass them like this:
<?= route('posts.show', $post->id) ?>
What do you think? Let me know in a comment below! If you like this article, follow me on Facebook and Youtube!