Home > Software design >  Php : match url using regex and extract values if pattern matches
Php : match url using regex and extract values if pattern matches

Time:03-21

Hi i am learning dynamic urls in php for creating custom router

i set the routes using this method

$router->get("/home",function(){
echo "this is home";
});

I didnt thought before that the first parameter(my router path) of get() could also be written as /profile/{user}/id/{id} I tried using regex for path in get() and use preg match to return value but not happy with output as it requires regex every time i set new route

i would like to know how i would simply set the route like /profile/{user}/id/{id} or /profile/{var : user}/id/{int : id} and and get output like if route-pattern matches return an array with key value where key is user and value is from string and so on

defined routes : requested routes : output

/home                   form action : /home                     o/p = array()
/home/{page}            form action : /home/about               o/p = array(page=>'about')
/profile/{name}/id/{id} form action : /profile/stackuser/id/200 o/p = array(name=>stackuser,id=>200)

CodePudding user response:

You could convert your routes into regexps with a named capturing groups:

$routes = [
  '/profile/{user}/id/{id}',
  '/this/will/not/match/for/sure',
];

$routes_regexps = array_map(
  function($route){
    return 
      '#^' // RE delimiter and a string start 
        /* Translate 
          {something}
          substrings into regexp named matches like
          (?<something>[^/] )
        */
      . preg_replace("/\{(.*?)\}/", '(?<$1>[^/] ?)', $route) 
      . '$#' ; // String end and a RE delimiter
  }, 
  $routes
);

And then match the URL path through those RE's:

$test_urls = [
  '/profile/some_username/id/25',
  '/this/will/not/match'
];

foreach( $routes_regexps as $i => $re ){

  print "Route is: {$routes[$i]}\n";
  print "RE is: $re\n";

  foreach( $test_urls as $url ){

    $matches = [];
    if( preg_match_all($re,$url,$matches) ){
      
      print "Url [$url] did match the route, variables are: \n";
      print "User: {$matches['user'][0]}\n";
      print "id: {$matches['id'][0]}\n";

    } else {
      print "Url [$url] didn't match\n";
    }  

  }
}

But the way I'd prefer is to convert both routes and the URL path to arrays and compare element by element, checking if route component is something like {variable name here}.

  • Related