REGEXless dispatcher
The original index is never used and can currently be removed from both url and filter.

Your use of temporary variables is actually making the code less easy to read.


Replace the length indexes which are just a temporary values to check for validity.  I call this pathCount in the code below.
Replace parameters and the merging that you do with just continually adding to the array.  Adding to the array should overwrite any existing values equivalently to the array_merge operation.


I would also change the name of $key to something else as it confuses me with it being an array key. (I would call it $component or something similar).  I didn't make this change in the code below.

Edit:

In fact further to this $url and $filter are also temporary variables hurting your readability.  They could be replaced at the appropriate points with:

 $urlPath = explode('/', parse_url($url, PHP_URL_PATH);
 $filterPath = explode('/', $filter);


The code then becomes (not tested):

function ay_dispatcher($url, $routes)
{
   $urlPath = explode('/', parse_url($url, PHP_URL_PATH));

   foreach($routes as $filter =&gt; $data)
   {
      $filterPath = explode('/', $filter);

      if (count($filterPath) !== $count($urlPath))
      {
          continue;
      }

      if(!array_key_exists('parameters', $data))
      {
          $data['parameters'] = array();
      }

      foreach($filterPath as $i =&gt; $key)
      {
          if(strpos($key, ':') === 0)
          {
              $data['parameters'][substr($key, 1)] = $urlPath[$i];
          }
          // this filter is irrelevent
          else if($key !== $urlPath[$i])
          {       
              continue 2;
          }
      }

      return $data;
   }

   return FALSE;
}


I am not sure that your logic for counting the filter path should just be a count?  Perhaps you need a function for that as parameters used in the filter would effect the count?