MVC Routing
Je wilt altijd flexibiliteit houden over hoe je routes eruit zien.
Conclusie: routes netjes opslaan, en maken zoals je ze zelf wil. Geen gedoe met bestandsnamen.
route = contact:
- controller = ContactController
- action = IndexAction
index.php
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
// index.php
require "Request.php";
require "Router.php";
$router = new Router;
$router->add(array("route" => "", "destination" => "welcome.php", "methods" => array("all")));
$router->add(array("route" => "help", "destination" => "help.php", "methods" => array("GET"))); // kan het zo goed "all" zijn (alle methods)
$router->add(array("route" => "contact", "destination" => "contact.php", "methods" => array("GET"))); // kan het zo goed "all" zijn (alle methods)
$router->add(array("route" => "submit", "destination" => "submit.php", "methods" => array("POST")));
// Ingewikkelder
$router->add(array("route" => "shop/product/info/", "destination" => "productInfo.php", "methods" => array("GET", "POST"));
$router->matchRequest(new Request);
?>
// index.php
require "Request.php";
require "Router.php";
$router = new Router;
$router->add(array("route" => "", "destination" => "welcome.php", "methods" => array("all")));
$router->add(array("route" => "help", "destination" => "help.php", "methods" => array("GET"))); // kan het zo goed "all" zijn (alle methods)
$router->add(array("route" => "contact", "destination" => "contact.php", "methods" => array("GET"))); // kan het zo goed "all" zijn (alle methods)
$router->add(array("route" => "submit", "destination" => "submit.php", "methods" => array("POST")));
// Ingewikkelder
$router->add(array("route" => "shop/product/info/", "destination" => "productInfo.php", "methods" => array("GET", "POST"));
$router->matchRequest(new Request);
?>
Router.php
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?php
class Router {
private $_routes;
private $_destination;
private $_notFoundDestination = "notfound.php";
public function add(array $route = array()) {
$this->_routes[] = $route;
}
public function matchRequest(Request $request) {
if($request->getArgument('route') == "") {
$this->_destination = "welcome.php"; // Startpagina, normaal index.php
$this->navigate();
} else {
for($i = 0; $i < count($this->_routes); $i++) {
if($this->_routes[$i]["route"] == $request->getArgument('route')) {
if(in_array($request->getMethod(), $this->_routes[$i]["methods"]) || in_array("all", $this->_routes[$i]["methods"])) {
$this->_destination = $this->_routes[$i]["destination"];
$this->navigate();
return;
}
$this->notFound(); // verkeerde method
return;
}
}
$this->notFound(); // Loop door alle mogelijke routes gedaan, niks gevonden
}
}
public function navigate() {
require $this->_destination;
}
public function notFound() {
require $this->_notFoundDestination; // Error 404 pagina
}
}
?>
class Router {
private $_routes;
private $_destination;
private $_notFoundDestination = "notfound.php";
public function add(array $route = array()) {
$this->_routes[] = $route;
}
public function matchRequest(Request $request) {
if($request->getArgument('route') == "") {
$this->_destination = "welcome.php"; // Startpagina, normaal index.php
$this->navigate();
} else {
for($i = 0; $i < count($this->_routes); $i++) {
if($this->_routes[$i]["route"] == $request->getArgument('route')) {
if(in_array($request->getMethod(), $this->_routes[$i]["methods"]) || in_array("all", $this->_routes[$i]["methods"])) {
$this->_destination = $this->_routes[$i]["destination"];
$this->navigate();
return;
}
$this->notFound(); // verkeerde method
return;
}
}
$this->notFound(); // Loop door alle mogelijke routes gedaan, niks gevonden
}
}
public function navigate() {
require $this->_destination;
}
public function notFound() {
require $this->_notFoundDestination; // Error 404 pagina
}
}
?>
Request.php
Code (php)
- Je kunt bij het definieren van een route aangeven of deze werkt op alle methods, of alleen post of get methods.
- Je geeft bij de route de bestandsnaam (of pad naar een bestand), de route is daar onafhankelijk van
Graag hoor ik commentaar, en dat zal vast wel veel zijn. Want ik weet dat deze code niet perfect is. Toch wilde ik het laten zien.
Gewijzigd op 16/12/2013 20:51:40 door Mark Hogeveen
http://www.phphulp.nl/php/forum/topic/mvc-routing/93198
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$router->add(array("route" => "forum/topic/:slug/:id", "destination" => "forum-showtopic.php", "methods" => array("all")));
// de controller
class ShowtopicController extends BaseController
{
public function indexAction($slug, $id)
{
// test
echo 'slug: ' . $slug . '<br>';
echo 'id: ' . $id . '<br>';
}
}
?>
$router->add(array("route" => "forum/topic/:slug/:id", "destination" => "forum-showtopic.php", "methods" => array("all")));
// de controller
class ShowtopicController extends BaseController
{
public function indexAction($slug, $id)
{
// test
echo 'slug: ' . $slug . '<br>';
echo 'id: ' . $id . '<br>';
}
}
?>
Gewijzigd op 16/12/2013 23:47:01 door Frank Nietbelangrijk
@Frank, wat wordt bedoeld met "slug" en wat houdt methods "all" in?
En je tweede vraag zou je aan Harry moeten vragen maar ik dacht dat het voor GET & POST staat.
Wat is dan de bedoeling van een slug? Geef je daar eigenlijk de action mee aan? Ik dacht dat wat jij een slug noemt gewoon bij de route hoort. Dus zeg maar zoiets:
route = "forum/topic/hoe-kan-ik-grote-bestanden-uploaden/:id"
Of... wacht even.. bedoel je dat het de (variabele) titel van een topic is? En zo ja, waarom dan niet:
route = "forum/topic/:title/:id"
>> En je tweede vraag zou je aan Harry moeten vragen maar ik dacht dat het voor GET & POST staat.
oké
Omdat we dat nou eenmaal de slug noemen. Dat komt omdat het niet de titel is, je hebt spaties vervangen met dashes, alles gelowercased en url-unsafe-characters eruit gehaald. Dat noemen we een slugified title, afgekort een slug.
forum/user/wouterj/123
Is "wouterj" dan ook een "slug"?
Wat versta je precies onder een slug? En is iedere variabele die in de url staat en niet een id is automatisch een slug?
Maar ik had verwacht dat mijn code eigenlijk een rommeltje was?
De Request class stelt eigenlijk niks voor. Ik zou niet weten wat ik er mee moet.
Maar ja, omdat je het anders zielig is dat je het verkeerde aanleerd :)
- Routes zijn ook objecten, een Route object dus.
- Het matchen van een URL zou je moeten overlaten aan het Route object, dat is degene die weet wat er in het Route object staat, de Router mag daar niks van weten. Als je het heel strict bekijkt ga je nog een stap verder en zeg je dat je niet wilt beperken op URLs, dan maak je nog een UrlMatcher klasse die het matchen regelt.
- Kijk eens naar php namespaces en autoloading
- De router is alleen voor het vinden van een route, het bepalen wat de not found route is en het bepalen wat de destination is is niet het doel van de Router.
- niet elke variabele die je in je klasse gebruikt is een property van die klasse. Slechts een paar zijn er een property.
- "$this->_destination = "welcome.php"; // Startpagina, normaal index.php" bepaal niks in de klasse zelf. Als je nu welcome.php aanpast moet je je klasse aanpassen, en klassen aanpassen voor zulke dingen is verboden. Je startpagina is gewoon een route zoals elke andere.
- Je gebruikt een hele vreemde manier wat betreft het laden van een controller. Wat doe je precies in een controller, ik heb niet het idee dat je daar iets van begrepen hebt (sorry).
- Je Request klasse is erg gelimiteerd. Het is nu gebonden aan: Het gebruik van superglobals. (gebruik nooit superglobals in een klasse!) Tevens is getArgument nu gebonden aan het gebruik van $_GET. Ik zou altijd werken met $_SERVER['PATH_INFO']
Wat ik eigenlijk wel begrijp, maar niet het voordeel van inzie is het volgende:
Een simpele doorsnee route ziet er zo uit: /controller/action/paramaters
Het is dan de bedoeling dat de gevraagde controller wordt aangeroepen, en dat een methode van die controller wordt aangeroepen, die ook in de route staat.
controller/action/parameters =
album/bekijk_foto/1042 =
AlbumController/view/1042 zegt eigenlijk:
$AlbumController->view(1042);
- Wat als je meerdere controllers nodig hebt?
- Wat als je meerdere parameters hebt?
- Hoe doet mod_rewrite de GET variabelen normaal doorgeven? Daarmee bedoel ik: ?action=activate&user=123
Die zou kunnen worden herschreven naar /activate/123 of niet?
De namen van de parameters zijn weg! Hoe doe ik nou in mij PHP aangeven welke parameter ik wil? ($_GET['action'] kan toch niet meer? naam is weg)
Gewijzigd op 17/12/2013 17:47:14 door Mark Hogeveen
http://kohanaframework.org/3.3/guide/kohana/routing#request-parameters om te zien hoe Kohana het beschikbaar stelt.
Het hangt er vanaf hoe geavanceerd je routes zijn. Kijk eens op