1

Possible Duplicate:
CMS Routing in MVC

I want to implement the MVC design structure and currently struggeling with an good solution to parse requested views.

In my routing file, I have following code:

public function parseRequestedView() {

   $this->ressource_requested = explode('/', trim($_GET['view'], '/'));

   // e.g.: http://www.foo.com/article/{id}/comments/show
   if (!empty($this->ressource_requested[3])) {

      // Format: [0] viewpoint (article), [1] child (comments), [2] action (show), [3] reference ({id}),
      //         [4] additional information (from $_POST)
      return array($this->ressource_requested[0], $this->ressource_requested[2], $this->ressource_requested[3],
                   $this->ressource_requested[1], $_POST);

   // e.g.: http://www.foo.com/article/{id}/show
   } elseif (!empty($this->ressource_requested[2])) {

      return array($this->ressource_requested[0], NULL, $this->ressource_requested[2], $this->ressource_requested[1],
                   $_POST);

   // e.g.: http://www.foo.com/archive/show
   } else {

      return array($this->ressource_requested[0], NULL, $this->ressource_requested[1], NULL, NULL);

   }

}

The idea is, no matter what a visitor types into the browser, the function parses the request and always returns the same formatted array/output. The first segment of the URL following the hostname is always the main viewpoint (e.g.: article). In the end, I am including the view through another function called includeTemplateFile(). The files have this naming convention:

viewpoint.child.action.template.php
e.g.: article.comments.show.template.php

My question is now: Is there a more elegant solution? I read some of the turorials/articles (e.g.: http://johnsquibb.com/tutorials/mvc-framework-in-1-hour-part-one) regarding this topic, but I do not like most solutions since they are not well designed.

Here is the content of the .htaccess file:

RewriteEngine on

RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule ^(.*)$ index.php?view=$1 [L,QSA]

Thanks in advance.

Community
  • 1
  • 1
  • First, a big thanks for the answers. But let me point out, that my question is not a duplicate since I am asking if my solution is good designed or if there is a better one. I do not have any problems with the routing library. Or did I misread something in the posted questions? –  Dec 18 '12 at 14:41

1 Answers1

0

Ok I'm just gonna start by saying I'm no expert in PHP and I recommend using a framework such as symphony to do your routing, but here is one possible solution that you could use.

function regexPath($path)
{
    return '#' . str_replace([":int:", ":string:"], ["\d+", ".+"], $path) . '#';
}

function parseRequestedView($url)
{
    $ressource_requested = explode('/', trim($url, '/'));


    // define our routes, and the indices that each route will use (from the exploded url)
    // this could be defined as another parameter or as a member of the class
    $routes = [
        regexPath("article/:int:/comments/show") => [0,  2, 3,  1], // will return array(resource[0], resource[2], resource[3], resource[1]), etc
        regexPath("article/:int:/show")          => [0, -1, 2,  1], // -1 will return a null
        regexPath("archive/show")                => [0, -1, 1, -1]
    ];


    // go through each route, checking to see if we have a match
    foreach ($routes as $regex => $indices)
    {
        if (preg_match($regex, $url))
        {
            // it matched, so go over the index's provided and put that data into our route array to be returned
            foreach ($indices as $index)
            {
                $route[] = $index > -1 ? $ressource_requested[$index] : null;
            }

            // include the post data (not really nessesary)
            $route[] = $_POST; // unnessesary to pass $_POST data through function, because it is global

            return $route;
        }
    }

    return null; // or some default route maybe?
}

$route = parseRequestedView("article/13/comments/show");

echo '<pre>';
print_r($route);
echo '</pre>';

/* returns:
Array
(
    [0] => article
    [1] => comments
    [2] => show
    [3] => 13
    [4] => Array // this is our $_POST data
        (
        )

)
*/
Supericy
  • 5,866
  • 1
  • 21
  • 25
  • A huge thanks. Your solution is far more elegant than mine. Sadly, I cannot use any third party framework (regulations). –  Dec 18 '12 at 14:45
  • One more thing: Could you please explain, what the [":int:", ":string:"] and ["\d+", ".+"] in str_replace([":int:", ":string:"], ["\d+", ".+"], $path) exactly do? Many thanks in advance. –  Dec 18 '12 at 14:57
  • That is basically just for convenience. It converts the "more readable" string into a regex pattern. There are lots of good resources about it online. – Supericy Dec 18 '12 at 18:40