Question

I am working on a custom PHP URL routing class, but I need some help on the regular expressions. I want users to add routes like this:

$router->addRoute('users/:id', 'users/view/');

After adding the route the script needs to check if the requested URL matches the defined format (users/:id) and call the view method of the users controller. Also it needs to pass the id as parameter to the view method.

My addRoute method looks like this:

public function addRoute($url, $target)
{
    $this->routes[] = ['url' => $url, 'target' => $target];
}

The methods thats handle the routes looks like this:

public function routes()
{
    foreach($this->routes as  $route) {

        $pattern = $route['url'];

        // Check if the route url contains :id
        if (strpos($route['url'], ':id'))
        {
            // Build the pattern
            $pattern = str_replace(':id','(\d+)', $pattern);
        }

        echo $pattern . '<br />' . $this->_url;

        if (preg_match_all('~' . $pattern . '~u', $this->_url, $matches))
        {
            $this->url_parts = explode('/', $route['target']);
            $this->_params = $matches;
        }
    }
}

Currently the script loop through the routes and checks if the url contains :id. If so it will be replaced by (\d+).

Then the scripts checks if the requested url matches the pattern and set some variables.

So far everything works but, after some testing there are some problems with matching the url.

I want the script to only allow urls that are in the format of /users/:id, but when I call the following url it will pass to /users/1/test.

How can I prevent the script from allow this urls, and only let it match the defined format?

Was it helpful?

Solution 2

I managed the problem by myself. I had to add a ^ before the expression and +$ after it. So that the function looks like this:

private function routes()
{
    // Loop through the routes
    foreach($this->routes as  $route) 
    {
        // Set the pattern to the matching url
        $pattern = $route['url'];

        // Check if the pattern contains :id
        if (strpos($route['url'], ':id'))
        {
            // Build the pattern
            $pattern = str_replace(':id','([0-9]+)', $pattern);
        }

        // Check if the requested url matches the pattern
        if (preg_match_all('~^' . $pattern . '+$~', $this->_url, $matches))
        {
            // If so, set the url_parts var
            $this->url_parts = explode('/', $route['target']);

            // Remove the first index of the matches array
            array_shift($matches);

            // Set the params var
            $this->_params = $matches;
        }
    }
}

OTHER TIPS

Try the following:

$router->addRoute('users/(\d+)$', 'users/view/');
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top