Beste Developers,

Ik zie vaak allemaal ingewikkelde routers tegen komen op internet.

Na even te zoeken kwam ik een vrij simpele router tegen hier op PHPHulp.

Wat is de reden van een uitgebreide moeilijke router? Na mijn mening is dit toch prima?

Enige probleem dat ik nu nog heb, is dat wanneer ik nu naar /artikel/bewerk/234/ dat hij de route /artikel/ pakt, hoe kan ik dit op de beste manier oplossen? Alles een prioriteit meegeven, sorteren op langste route? Wat is de beste manier hiervoor? Of gewoon een kwestie van de routes aanmaken in de goede volgorde?


<?php
class Router
{
    private $_routes;

    public function __construct()
    {
        $this->_routes = array();
    }

    public function setRoute( Route $route )
    {
        $this->_routes[] = $route;
    }

    public function match( $query )
    {
        $routes = $this->_routes;
        if( $routes )
        {
            foreach( $routes as $route )
            {
                $match = $route->match( $query );
                if( $match )
                {
                    return $match;
                }
            }
        }
        return false;
    }
}

class Route
{
    private $_regex;
    private $_controller;

    public function __construct( $pattern, $controller )
    {
        $this->_regex = preg_replace( '#:([a-z])+#','(?P<$1>[^/]+)', $pattern );
        $this->_controller = $controller;
    }

    public function match( $query )
    {
        if( !preg_match( '#'.$this->_regex.'#', $query, $matches ) )
        {
            return false;
        }

        $controller = new Controller();
        $controller->setName( $this->_controller );
        return $controller;
    }
}

class Controller
{
    private $_name;

    public function setName( $name )
    {
        $this->_name = $name;
    }
    public function getName()
    {
        return $this->_name;
    }
}

$router = new Router();
$router->setRoute( new Route( '/artikel/', 'article.view.module') );
$router->setRoute( new Route( '/artikel/bewerk/:id', 'article.edit.module') );
$router->setRoute( new Route( '/artikel/verwijder/:id', 'article.delete.module') );

$controller = $router->match( $request->server( 'REDIRECT_URL' ) );
?>


Hint: je router lijkt op de URI-router van bijvoorbeeld CodeIgniter. Een URL wordt dan min of meer met een explode op / gekoppeld aan een controller class/method:

example.com/controller/function/id

Dat is hetzelfde als je probeert te bereiken met:

/artikel/bewerk/234/

Als je daarmee alleen bij de class /artikel/ uitkomt, mis je dus nog de mapping naar de methode/functie.
Ward, volgens mij snap je niet helemaal wat ik bedoel. Het gaat met namen over de routes die aangemaakt worden.
Routes worden afgehandeld in de volgorde waarin je ze definieert: zodra er een match is, wordt die route gekozen. Je moet daarom werken van specifiek (een lang pad zoals /artikel/bewerk/234/) naar generiek (een kort pad zoals /artikel/).

Goed overzicht van de routing in CodeIgniter en daarin ook de eerste “note”:

http://ellislab.com/codeigniter/user-guide/general/routing.html
Of je maakt gebruik van ^ en $ in je regex, waardoor je dat probleem niet meer hebt.

Waarom deze Router niet snel gebruikt zou worden in grote applicaties en grote frameworks:
- Je hebt geen collections. Hierdoor kun je bijv. niet een hele groep routes tegelijkertijd een prefix meegeven. Denk bijv. aan een aparte groep voor admin routes, die je dan de '/admin' prefix geeft.
- Je mist het gebruik van requirements. Ik kan bijv. niet aangeven dat :id een getal moet zijn.
- Je mist default values, ik kan niet zeggen dat /:slug standaard de waarde 'home' krijgt.
- De Route object mag echt niet gaan bepalen dat er een controller naam wordt teruggegeven. Dat is de taak van een FrontController of Kernel.
- De manier hoe jij met controllers omgaat vind ik nu nog een beetje vreemd, maar misschien wordt het straks wel mooi.
Ik kom toch nog even terug op mijn topic, ik heb het probleem nog steeds niet kunnen oplossen.

Het probleem dat mijn router niet doet wat ik wil en nergens goede / mooie voorbeelden kan vinden zorgt er steeds voor dat ik vast loop.

Graag wil ik gebruik maken van het HMVC pattern.

<#id> moet een getal zijn
<:slug> moet een string zijn

Hopelijk kunnen jullie mij de goede richting in duwen.
*schop*

Ook lees ik dat vele bij het toevoegen van een route een array meesturen met de Contoller, Module en Action.
Bijvoorbeeld:

$router->setRoute( new Route( '/artikel/bewerk/:id', array( 'module' => 'article', 'controller' => 'edit', 'action' => 'index' ) ) );

Waarom wordt er gekozen voor een array? Waarom wordt er niet gekozen voor deze manier?

$router->setRoute( new Route( '/artikel/bewerk/:id', 'article', 'edit', 'index' ) );
waarom doe je het niet gewoon zo?
<?php

$routes = array(
'home',
'contact',
'contact/thanks'
);


$uri = $_SERVER['PATH_INFO'];
$uri = strtolower($uri);
$uri = substr($uri, 1);

if(array_search($uri , $routes))
echo $uri;
else
echo 'not found';

?>
@Frank, dit is totaal niet wat ik wil.

Iemand anders die er even een oog op wil werpen?
@Frank: dat is iets heel anders dan wat de topic starter vraagt :)

@Tom: waarom er voor een array wordt gekozen? Stel dat de routes uit een configuratiebestand komen (wat heel gebruikelijk is) dan kun je ze via een foreach-loop gemakkelijk inladen. Dan krijg je zoiets als:


<?php
foreach ($routes as $route) {
  $router->setRoute(new Route($route['url'], $route['parameters']));
}
?>
Tom Swinkels op 22/02/2013 23:03:53

Enige probleem dat ik nu nog heb, is dat wanneer ik nu naar /artikel/bewerk/234/ dat hij de route /artikel/ pakt, hoe kan ik dit op de beste manier oplossen?


Dat is waar ik een oplossing op gaf dat natuurlijk verder uitgewerkt kan worden.

Reageren