PHP preg_match用于路由

I have ventured into a number of other questions here but couldn't find an actual answer to my scenario.

I am working on modifying my framework a little to have multiple "applications" run from the same framework base structure. Essentially this will change my url structure which is a little complicated for me to approach at the moment.

I have the following potential url structures:

  1. :module\:controller\:action\:properties
  2. :controller\action\:properties
  3. :module\controller
  4. :controller

The problem is that I need to be able to determine while routing if the first parameter is indeed a module call (such as cms) or if it's a controller call which uses the "default" module (site).

An example here would be:

  1. http://domain.com/cms/pages/ (needs to use cms as module, pages for controller and defaults to index as action)
  2. http://domain.com/articles/view/11 (needs to use site as the module (default module), articles as controller, view as action and 11 as property).

My 2nd issue I have is that my preg_match at the moment is strict so I need to add a route for each possible scenario, which can be become quite lengthy and I am sure there is a better solution to this.

As an example I have a route setup for /:module/:controller which will match say /cms/users but in some cases I may need to match partial routes and route a user to another place. Say the requested module and controller exists but the action doesn't. If I want to setup /cms/:controller/:action and the :action does not exists I do not want it to skip it as a match, but rather want to setup a fallback for that specific match to say default to /cms/notfound/ or something.

Here is my code I use at the moment:

 // EXAMPLE OF MY ROUTES (used within the router object for matching):
var $routes = array(
    "/" => ["base" => "\application\site\controllers","controller" => "static", "action" => "index","properties" => ""],
    "/cms" => ["base" => "\application\cms\controllers","controller" => "users", "action" => "login","properties" => ""],
    "/cms/:controller/:action" => ["base" => "\application\cms\controllers","controller" => "", "action" => "","properties" => ""]
);

 // MATCH METHOD IN ROUTER:

 public function match($request) {

 // $request can be anything from / to /users/login 

    if (($strpos = strpos($request, '?')) !== false) {
        $request = substr($request, 0, $strpos);
    }

 // Tokens used within router:
 $tokens = array(
        ":application" => "(?P<application>[a-zA-Z\-\_]+)",
        ":controller" => "(?P<controller>[a-zA-Z\-\_]+)",
        ":action" => "(?P<action>[a-zA-Z\-\_]+)",
        ":properties" => "(?P<properties>[a-zA-Z0-9\-\_\=\;]+)",
        ":id" => "([0-9])"
    );

    foreach ($this->routes as $route => $properties) {
        $pattern = '#^/?' . strtr($route, $tokens) . '/?$#';
        if (preg_match($pattern, $request, $matches)) {

            unset($matches[0]);
            // Set the application:
            if (!isset($matches[1])) {
                $match['application'] = $this->config->default_application;
            } else {
                if (in_array($matches[1], $this->config->applications)) {
                    $match['application'] = $matches[1];
                } else {
                    return false;
                }
            }

            // Set the controller and action:
            if (array_key_exists($match['application'], $this->config->application_routes)) {
                $match['controller'] = (isset($matches[2]) ? $matches[2] : $this->config->application_routes[$match['application']]['controller']);
                $match['action'] = (isset($matches[3]) ? $matches[3] : $this->config->application_routes[$match['application']]['action']);
            }

            // Set the properties:
            $match['properties'] = (isset($matches[4]) ? $this->generate_properties($matches[4]) : false);
            return $match;
        }
    }
    return false;
}

So essentially I need the following advice:

  1. Best way to setup the returning $match array (to assign module, controller, action and properties)
  2. How to make preg_match to be less "strict" (so allow for partial matches and rather have it route to another key within my map for say "notfound" etc.