3

I have some problems when trying to make a match with my URL with my regex pattern in PHP.

my regex:

/article/([0-9A-Za-z]++)/post/([0-9A-Za-z-_]++)

public function matches(Route $route){
    $uri = filter_var(strip_tags($_SERVER['REQUEST_URI']), FILTER_SANITIZE_URL);
    if (preg_match('#' . "/article/([0-9A-Za-z]++)/post/([0-9A-Za-z-_]++)" . '#i', $uri, $this->matches)) {
        return true;
    }
    return false;
}

example 1: VALID MATCH (good)

/article/AB545455DSAF54FSA45S4F4/post/FGFG-FGFGF-5FG54FGF-FGFGFG

but also matches this (bad):

/article/AB545455DSAF54FSA45S4F4/post/FGFG-FGFGF-5FG54FGF-FGFGFG/fgfg/fgfgfg/fgf

I want only to match the first example, so how do i fix this? thanks

JuanLT
  • 53
  • 1
  • 6

1 Answers1

4

Add a terminating anchor to your regex:

/article/([0-9A-Za-z]+)/post/([0-9A-Za-z-_]+)$
                                             ^^^

The anchor will ensure that no more subdirectories can appear after the final component.

public function matches(Route $route){
    $uri = filter_var(strip_tags($_SERVER['REQUEST_URI']), FILTER_SANITIZE_URL);
    if (preg_match('~/article/[0-9A-Za-z]+/post/[0-9A-Za-z_-]+$~", $this->matches)) {
        return true;
    }
    return false;
}

Note that matching something in regex one or more times uses a single plus, not two of them.

I may not have your exact code working here, but the pattern I suggest appears to work in the demo below.

Demo

Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360
  • that's awesome, thanks for the advice. i use ++ because I saw code on github that used it too `protected $match_types = array( 'i' => '[0-9]++', 'a' => '[0-9A-Za-z]++', 'h' => '[0-9A-Fa-f]++', 's' => '[0-9A-Za-z-_]++', '*' => '.+?', '**' => '.++', '' => '[^/\.]++' );` – JuanLT Jan 24 '18 at 03:56
  • @Tim Biegeleisen : I was thinking you as a database guy :) – sumit Jan 24 '18 at 04:05
  • thanks for the Demo, now it works perfectly, here is the complete code: https://github.com/Jlopez2045/SimpleRouter/blob/master/router/router.php – JuanLT Jan 24 '18 at 04:13
  • 1
    @sumit I'm a Stack omnivore. If it has a heartbeat, I'll eat it :-) – Tim Biegeleisen Jan 24 '18 at 04:15
  • 1
    @Tim please change the delimiter to avoid the in-pattern escaping. Also, please move the hyphen to the front or back of the character class so that a range is not created. Finally, the capture groups are not necessary. – mickmackusa Jan 24 '18 at 15:20
  • @mickmackusa Let me know if I omitted anything. Didn't know that hyphen could also start a character class, +1 to your comment. – Tim Biegeleisen Jan 24 '18 at 15:22
  • 1
    Just the pattern delimiters. I would probably go with `~`. Then you can "un-escape" the `/`s in the pattern. `~/article/[0-9A-Za-z]+/post/[0-9A-Za-z_-]+$~` And now that I think about it `\w` would be well placed in this pattern for brevity. https://regex101.com/r/Ty1jVf/1 – mickmackusa Jan 24 '18 at 15:23
  • Hmm. I just learned something. `[0-9A-Za-z-_]` actually wasn't generating a range of characters because it immediately followed a range of characters. Thanks for updating anyhow. – mickmackusa Jan 24 '18 at 15:31
  • Yeah...it was working in the demo (well...at least a very similar pattern was working in the demo). Yay for PHP. – Tim Biegeleisen Jan 24 '18 at 15:32
  • Thanks for your comments guys helped me a lot. then I will use this regexp `~/?article/[0-9A-Za-z]+/post/[\w-]+/?$~i ` – JuanLT Jan 24 '18 at 17:21