title: Php router, extracting keys from uri
body: <p>Hey folks! I need some help with regular expressions/etc. I need to extract virtual keys from url, some sort of router in application. Here are the params:</p>
  
  <pre><code>Rule: /books/:category/:id/:keyname
  Data: /books/php/12345/this-is-a-test-keyname
  </code></pre>
  
  <p>Output should be something like that:</p>
  
  <pre><code>array(
    'category' =&gt; 'php',
    'id' =&gt; '12345',
    'keyname' =&gt; 'this-is-a-test-keyname'
  );
  </code></pre>
  
  <p>So, the question is: how can i do this in php? </p>
  
  <p>P.S Combinations of rules can vary. So, the main keys are the words with ':' symbol. for example like this:</p>
  
  <pre><code>/book-:id/:category/:keyname
  /book/:id_:category~:keyname
  </code></pre>
  
  <p>P.S. 2: This is a piece of code i had before. It is working, but not flexible.</p>
  
  <pre><code>function rule_process($rule, $data) {
          // extract chunks       
          $ruleItems = explode('/',$rule);
          $dataItems = explode('/',$data);
  
          // remove empty items
          array_clean(&amp;$ruleItems);
          array_clean(&amp;$dataItems);
  
          // rule and data supposed to have the same structure
          if (count($ruleItems) == count($dataItems)) {
              $result = array();
  
              foreach($ruleItems as $ruleKey =&gt; $ruleValue) {
                  // check if the chunk is a key
                  if (preg_match('/^:[\w]{1,}$/',$ruleValue)) {
                      // ok, found key, adding data to result
                      $ruleValue = substr($ruleValue,1);
                      $result[$ruleValue] = $dataItems[$ruleKey];
                  }
              }
  
              if (count($result) &gt; 0) return $result;
              unset($result);
          }
  
          return false;
      }
  
      function array_clean($array) {
          foreach($array as $key =&gt; $value) {
              if (strlen($value) == 0) unset($array[$key]);
          }   
      }
  </code></pre>
  
  <p>In fact this version of router can be enough for me, but im just interested how to make the flexible solution. By the way, some tests: (30 times of 10000 operations):</p>
  
  <pre><code>TEST #0 =&gt; Time:0.689285993576, Failures: 0
  TEST #1 =&gt; Time:0.684408903122, Failures: 0
  TEST #2 =&gt; Time:0.683394908905, Failures: 0
  TEST #3 =&gt; Time:0.68522810936, Failures: 0
  TEST #4 =&gt; Time:0.681587934494, Failures: 0
  TEST #5 =&gt; Time:0.681943893433, Failures: 0
  TEST #6 =&gt; Time:0.683794975281, Failures: 0
  TEST #7 =&gt; Time:0.683885097504, Failures: 0
  TEST #8 =&gt; Time:0.684013843536, Failures: 0
  TEST #9 =&gt; Time:0.684071063995, Failures: 0
  TEST #10 =&gt; Time:0.685361146927, Failures: 0
  TEST #11 =&gt; Time:0.68728518486, Failures: 0
  TEST #12 =&gt; Time:0.688632011414, Failures: 0
  TEST #13 =&gt; Time:0.688556909561, Failures: 0
  TEST #14 =&gt; Time:0.688539981842, Failures: 0
  TEST #15 =&gt; Time:0.689876079559, Failures: 0
  TEST #16 =&gt; Time:0.689854860306, Failures: 0
  TEST #17 =&gt; Time:0.68727684021, Failures: 0
  TEST #18 =&gt; Time:0.686210155487, Failures: 0
  TEST #19 =&gt; Time:0.687953948975, Failures: 0
  TEST #20 =&gt; Time:0.687957048416, Failures: 0
  TEST #21 =&gt; Time:0.686664819717, Failures: 0
  TEST #22 =&gt; Time:0.686244010925, Failures: 0
  TEST #23 =&gt; Time:0.686643123627, Failures: 0
  TEST #24 =&gt; Time:0.685017108917, Failures: 0
  TEST #25 =&gt; Time:0.686363935471, Failures: 0
  TEST #26 =&gt; Time:0.687278985977, Failures: 0
  TEST #27 =&gt; Time:0.688650846481, Failures: 0
  TEST #28 =&gt; Time:0.688835144043, Failures: 0
  TEST #29 =&gt; Time:0.68886089325, Failures: 0
  </code></pre>
  
  <p>So, its fast enough. Im testing on regular laptop. So, for sure - this one can be used in real website. </p>
  
  <p>Any other solutions?</p>