3

I am trying to create a url router in PHP, that works like django's.

The problems is, I don't know php regular expressions very well.

I would like to be able to match urls like this:

/post/5/
/article/slug-goes-here/

I've got an array of regexes:

$urls = array(      
  "(^[/]$)" => "home.index",     
  "/post/(?P<post_id>\d+)/" => "home.post",    
);

The first regex in the array works to match the home page at / but I can't get the second one to work.

Here's the code I am using to match them:

foreach($urls as $regex => $mapper) {
    if (preg_match($regex, $uri, $matches)) {
    ...
    }
}

I should also note that in the example above, I am trying to match the post_id in the url: /post/5/ so that I can pass the 5 along to my method.

1
  • regexes should have proper delimiters Commented Nov 18, 2010 at 5:37

3 Answers 3

3

You must delimit the regex. Delimiting allows you to provide 'options' (such as 'i' for case insensitive matching) as part of the pattern:

,/post/(?P<post_id>\d+)/,

here, I have delimited the regex with commas.

As you have posted it, your regex was being delimited with /, which means it was treating everything after the second / as 'options', and only trying to match the "post" part.

The example you are trying to match against looks like it isn't what you're actually after based on your current regex.

If you are after a regex which will match something like;

/post/P1234/

Then, the following:

preg_match(',/post/(P\d+)/,', '/post/P1234/', $matches);
print_r($matches);

will result in:

Array
(
    [0] => /post/P1234/
    [1] => P1234
)

Hopefully that clears it up for you :)

Edit

Based on the comment to your OP, you are only trying to match a number after the /post/ part of the URL, so this slightly simplified version:

preg_match(',/post/(\d+)/,', '/post/1234/', $matches);
print_r($matches);

will result in:

Array
(
    [0] => /post/1234/
    [1] => 1234
)
Sign up to request clarification or add additional context in comments.

2 Comments

Ahhh, you made my night, thanks! I wish I could give you 20 votes for this.
Not a problem - delimiting the regex stung me quite a few times when I first started, and there aren't any explanations of it on php.net either!
1

If your second RegExp is meant to match urls like /article/slug-goes-here/, then the correct regular expression is

#\/article\/[\w-]+\/#

That should do it! Im not pretty sure about having to escape the /, so you can try without escaping them. The tag Im guessing is extracted from a .NET example, because that framework uses such tags to name matching groups.

I hope I can be of help!

Comments

1

php 5.2.2: Named subpatterns now accept the syntax (?<name>) and (?'name') as well as (?P<name>). Previous versions accepted only (?P<name>).

http://php.net/manual/fr/function.preg-match.php

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.