Welcome Guest, Not a member yet? Register   Sign In
{locale} placeholder in routes
#1

(This post was last modified: 06-11-2022, 04:35 AM by webdeveloper.)

Hi, I just want to share with you one of my changes I made to base router. Hopefully, it will save some time, to somebody who will search for the same solution like I did.

I was wondering why my project takes URL like

Code:
www.domain.com/blah/users

when I've never defined it? Why this works?

What I found out:

PHP Code:
$routes->group('{locale}', function ($routes) {
   $routes->group('users', function ($routes) {
      $routes->get('/''Users::index');
   });
}); 

{locale} will take ANYTHING

Why does all this URLs works?

Code:
www.domain.com/this/users
www.domain.com/makes/users
www.domain.com/no/users
www.domain.com/sense/users
www.domain.com/to/users
www.domain.com/me/users

{locale} should represent locale placeholder. According to me, it does not. It represent anything. Yes, it takes default locale value, if placeholder doesn't match any supported language.

PHP Code:
public $supportedLocales = ['en']; 

Only this should works.

Code:
www.domain.com/en/users

Changes I have made:

Create new file app/Services/Router.php

PHP Code:
<?php

namespace App\Services;

use 
CodeIgniter\HTTP\Request;
use 
CodeIgniter\Router\Exceptions\RedirectException;
use 
CodeIgniter\Router\RouteCollectionInterface;
use 
CodeIgniter\Router\Router as CoreRouter;

class 
Router extends CoreRouter
{
    public function __construct(RouteCollectionInterface $routes, ?Request $request null) {
        parent::__construct($routes$request);
    }

    /**
    * @param string $uri
    * @return bool
    * @throws RedirectException
    */
    protected function checkRoutes(string $uri): bool {
        $routes $this->collection->getRoutes($this->collection->getHTTPVerb());

        // Don't waste any time
        if (empty($routes)) {
            return false;
        }

        $uri $uri === '/' $uri trim($uri'/ ');

        // Loop through the route array looking for wildcards
        foreach ($routes as $key => $val) {
            // Reset localeSegment
            $localeSegment null;

            $key $key === '/' $key ltrim($key'/ ');

            $matchedKey $key;

            // Are we dealing with a locale?
            if (strpos($key'{locale}') !== false) {
                $localeSegment array_search('{locale}'preg_split('/[\/]*((^[a-zA-Z0-9])|\(([^()]*)\))*[\/]+/m'$key), true);

                // Replace it with a regex so it
                // will actually match.
                $key str_replace('/''\/'$key);
                $key str_replace('{locale}''[^\/]+'$key);
            }

            // Does the RegEx match?
            if (preg_match('#^' $key '$#u'$uri$matches)) {
                // Is this route supposed to redirect to another?
                if ($this->collection->isRedirect($key)) {
                    throw new RedirectException(is_array($val) ? key($val) : $val$this->collection->getRedirectCode($key));
                }
                // Store our locale so CodeIgniter object can
                // assign it to the Request.
                if (isset($localeSegment)) {
                    // The following may be inefficient, but doesn't upset NetBeans :-/
                    $temp = (explode('/'$uri));

                    /**
                    * CORE EDIT START
                    */
                    $supportedLocales config('App')->supportedLocales;

                    if (!in_array($temp[$localeSegment], $supportedLocales)) {
                        return false;
                    }
                    /**
                    * CORE EDIT END
                    */

                    $this->detectedLocale $temp[$localeSegment];
                }

                // Are we using Closures? If so, then we need
                // to collect the params into an array
                // so it can be passed to the controller method later.
                if (!is_string($val) && is_callable($val)) {
                    $this->controller $val;

                    // Remove the original string from the matches array
                    array_shift($matches);

                    $this->params $matches;

                    $this->matchedRoute = [
                        $matchedKey,
                        $val,
                    ];

                    $this->matchedRouteOptions $this->collection->getRoutesOptions($matchedKey);

                    return true;
                }
                // Are we using the default method for back-references?

                // Support resource route when function with subdirectory
                // ex: $routes->resource('Admin/Admins');
                if (strpos($val'$') !== false && strpos($key'(') !== false && strpos($key'/') !== false) {
                    $replacekey str_replace('/(.*)'''$key);
                    $val preg_replace('#^' $key '$#u'$val$uri);
                    $val str_replace($replacekeystr_replace('/''\\'$replacekey), $val);
                } else if (strpos($val'$') !== false && strpos($key'(') !== false) {
                    $val preg_replace('#^' $key '$#u'$val$uri);
                } else if (strpos($val'/') !== false) {
                    [
                        $controller,
                        $method,
                    ] = explode('::'$val);

                    // Only replace slashes in the controller, not in the method.
                    $controller str_replace('/''\\'$controller);

                    $val $controller '::' $method;
                }

                $this->setRequest(explode('/'$val));

                $this->matchedRoute = [
                    $matchedKey,
                    $val,
                ];

                $this->matchedRouteOptions $this->collection->getRoutesOptions($matchedKey);

                return true;
            }
        }

        return false;
    }


Check added part of code:

PHP Code:
/**
                     * CORE EDIT START
                     */
                    
$supportedLocales config('App')->supportedLocales;

                    if (!
in_array($temp[$localeSegment], $supportedLocales)) {
                        return 
false;
                    }
                    
/**
                     * CORE EDIT END
                     */ 


Add this use to app/Config/Services.php

PHP Code:
use App\Services\Router

Add custom router:

PHP Code:
    /**
    * @param RouteCollectionInterface|null  $routes
    * @param \CodeIgniter\HTTP\Request|null $request
    * @param bool                          $getShared
    * @return Router
    */
    public static function router(RouteCollectionInterface $routes null, \CodeIgniter\HTTP\Request $request null$getShared true): Router {
        if ($getShared) {
            return static::getSharedInstance('router'$routes$request);
        }

        $routes ??= AppServices::routes();
        $request ??= AppServices::request();

        return new Router($routes$request);
    
Reply


Messages In This Thread
{locale} placeholder in routes - by webdeveloper - 06-08-2022, 06:23 AM
RE: {locale} placeholder in routes - by InsiteFX - 06-09-2022, 11:57 PM
RE: {locale} placeholder in routes - by kenjis - 06-10-2022, 06:05 PM



Theme © iAndrew 2016 - Forum software by © MyBB