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' ) );
?>


Je kunt routing via URL's vergelijken met het ontleden van een zin: “X moet dit met dat doen.” Je hebt dan een onderwerp, een persoonsvorm, een lijdend voorwerp en een meewerkend voorwerp.

Met een array kun je in één keer een compleet verhaal vertellen. Met losse strings blijft het bij die ene instructie.
Met een array ben je ook veel meer flexibel.

En voor het antwoord op je vraag, die heb ik al lang beantwoord: "Of je maakt gebruik van ^ en $ in je regex, waardoor je dat probleem niet meer hebt."
Ward van der Put op 07/09/2013 15:40:44

Met een array kun je in één keer een compleet verhaal vertellen. Met losse strings blijft het bij die ene instructie.

Ward, is toch ook een kwestie van persoonlijke voorkeur?

Je zou een nieuwe user zo kunnen aanmaken:

$user = new User('Piet', 'Amsterdam', 35);

Of zo:
$user_info = array('Piet', 'Amsterdam', 35);
$user = new User($user_info);

Alleen als de informatie niet hard-coded is (wat meestal het geval is), en bijv. uit een configuratiebestand, formulier of database komt, dan lijkt me de laatste optie handiger.
Ja en nee Ozzie, kijk bijvoorbeeld naar je eigen voorbeeld:


<?php
$user = new User('Piet', 'Amsterdam', 35);
?>

Omdat we alleen de waarden noemen maar niet de eigenschappen, kunnen we nooit meer een 35-jarige Piet met voorlopig onbekende woonplaats verwerken:


<?php
$user = new User(35, 'Piet');
?>

Tweede punt is dat we zonder array niet Piet én zijn hele voetbalclub in één keer kunnen toevoegen. Nee, zonder array moeten we Piet, Jan, Joris, Corneel allemaal één voor één toevoegen.
Wat is vooral is in dit voorbeeld: Wie zegt dat die route aan een controller wordt gekoppeld? Dat is helemaal niet de taak van de Routing, dat moet iets als een ControllerResolver of FrontController doen. Omdat dat niet de taak is van Routing moet je in routing ook geen specifieke argumenten maken voor deze dingen.
@Ward: dan kun je toch ook zoiets doen:

<?php
$user = new User('Piet', false, 35); // woonplaats onbekend
?>

Een voetbalelftal toevoegen zou je inderdaad in een array doen... maar heeft niks met een user object te maken uiteraard. Maar wat zou dan de stelregel moeten zijn? Alles wat bij elkaar hoort (wat toebehoort aan 1 persoon of ding) in een array stoppen?
Bedankt voor alle reacties.

Ik denk dat je bij een route altijd een controller, action en model nodig hebt?

Maar ik snap jullie reacties, de vraag is alleen of dat hier voor komt?
Mijn voorkeur gaat altijd naar setters, omdat je dan namelijk weet wat er in die setter thuis hoort.
Wanneer je dus alles direct in de construct gooit, kan het zijn dat je soms niet meer weer welke volgorde e.t.c
Ik hou me altijd aan de volgende redenen, die ook vaak gebruikt worden door anderen:
- wanneer je iets instelt wat vaak hetzelfde is, gewoon echt de configuratie, gebruik je arrays
- anders gebruik je gewoon setters
- geef iets mee aan de constructor wanneer het nodig is voor de klasse om te werken. Een newsletter kan bijv. best werken zonder mailer, want je kan de nieuwsbrief ook als concept opslaan. Echter een router kan niet zonder routes en de request uri, die voeg je dus mee aan de constructor.

Tevens komen er in php 5.6 waarschijnlijk named arguments. Welke het probleem hierboven met het weglaten van de plaats een stuk makkelijker maakt:
<?php
new User('name' => 'Piet', 'age' => 35);
?>

Tevens zou ik nooit false durven gebruiken als ik geen waarde wil opgeven voor een string. Liever null, of nog beter een lege string.
Thanks Wouter. Voor wanneer staat versie 5.6 op de agenda?

"Tevens zou ik nooit false durven gebruiken als ik geen waarde wil opgeven voor een string. Liever null, of nog beter een lege string."

Klopt. Was ook maar even snel een voorbeeldje. Ik zou in dit geval voor null gaan.
maart/juni/juli 2014

Reageren