0

I am trying to turn a URI into key and value pairs in a URI class I have made. The URIs are clean and cannot be parsed into the $_GET variable. The solution has to be within PHP rather than Apache's mod_rewrite.

Consider this URI: /category/music/rows=30/page=12/

The desired key-value pairs I want from this are these:

array('category' <= 'music', 'rows' <= '30', 'page' <= '12')

To try and achieve this I wrote this example code:

$arr = array();
preg_match('/(category\/(?<category>[\w-_]+)|rows=(?<rows>\d+)|page=(?<page>\d+))+/', 
        "category/music/rows=30/page=12", $arr);
var_dump($arr);

Outputs:

array
  0 => string 'category/music' (length=14)
  1 => string 'category/music' (length=14)
  'category' => string 'music' (length=5)
  2 => string 'music' (length=5)

The thinking was that I wanted to match any in a group (/(match this|or this| or this)+/) once or more. I am assuming the problem here is that it matches once and then stops. Also, the parenthesis that group the or statement cause matches that aren't necessary to be stored (the string "category/music" is not required).

I have probably missed something obvious but I can't figure it out. I realize I could run preg_match three times but but it seems like there must be a way to do it in one expression. I also want to keep the code short.

Edit: preg_match_all works and I have altered the regex to this:

/category/(?[\w-_]+)|rows=(?\d+)|page=(?\d+)/

However, I now get this result:

array
  0 => 
    array
      0 => string 'category/music' (length=14)
      1 => string 'rows=30' (length=7)
      2 => string 'page=12' (length=7)
  'category' => 
    array
      0 => string 'music' (length=5)
      1 => string '' (length=0)
      2 => string '' (length=0)
  1 => 
    array
      0 => string 'music' (length=5)
      1 => string '' (length=0)
      2 => string '' (length=0)
  'rows' => 
    array
      0 => string '' (length=0)
      1 => string '30' (length=2)
      2 => string '' (length=0)
  2 => 
    array
      0 => string '' (length=0)
      1 => string '30' (length=2)
      2 => string '' (length=0)
  'page' => 
    array
      0 => string '' (length=0)
      1 => string '' (length=0)
      2 => string '12' (length=2)
  3 => 
    array
      0 => string '' (length=0)
      1 => string '' (length=0)
      2 => string '12' (length=2)

It would be ideal if it didn't also store "category/music","rows+30","page=12". It has also matched a lot of unnecessary blank strings.

1 Answer 1

1

Try using preg_match_all and see if that helps. preg_match stops after it finds the first match.

To get rid of match 1 ('category/music'), try to use a non-capturing group, so do:

(?:category\/(?<category>[\w-_]+)

instead of

(category\/(?<category>[\w-_]+)
Sign up to request clarification or add additional context in comments.

1 Comment

Ah excellent, preg_match_all does indeed work I can't believe I didn't realize that it was built for this exact purpose. I wonder if there is a way to do it with just a regular expression though. With preg_match_all I can just do this: /category\/(?<category>[\w-_]+)|rows=(?<rows>\d+)|page=(?<page>\d+)/. I still get matches for category/music rows=30 and page=12 though. I'll keep looking.

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.