Probleem met zelfgemaakte php router
Ik heb een php router gemaakt aan de hand van een tutorial.
Hier is de code van de htaccess:
Code (php)
1
2
3
4
5
6
2
3
4
5
6
RewriteEngine On
RewriteBase /example/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php?uri=$1 [QSA,L]
RewriteBase /example/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php?uri=$1 [QSA,L]
en hier de code van de router class zelf:
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
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
<?php
class Route
{
private $_uri = array();
private $_method = array();
/*
* Builds a collection of internal URL's to look for
* @param type $uri
*/
public function add($uri, $method = null)
{
$this->_uri[] = '/' . trim($uri, '/');
if($method != null){
$this->_method[] = $method;
}
}
public function submit()
{
$uriGetParam = isset($_GET['uri']) ? '/' . $_GET['uri'] : '/';
$routeFound = false;
foreach($this->_uri as $key => $value){
if(preg_match("#^$value$#",$uriGetParam)){
if(is_string($this->_method[$key])){
$routeFound = true;
$useMethod = $this->_method[$key];
new $useMethod();
}
else{
$routeFound = true;
call_user_func($this->_method[$key]);
}
}
}
if(!$routeFound){
http_response_code(404);
require_once 'pages/404.php';
}
}
}
?>
class Route
{
private $_uri = array();
private $_method = array();
/*
* Builds a collection of internal URL's to look for
* @param type $uri
*/
public function add($uri, $method = null)
{
$this->_uri[] = '/' . trim($uri, '/');
if($method != null){
$this->_method[] = $method;
}
}
public function submit()
{
$uriGetParam = isset($_GET['uri']) ? '/' . $_GET['uri'] : '/';
$routeFound = false;
foreach($this->_uri as $key => $value){
if(preg_match("#^$value$#",$uriGetParam)){
if(is_string($this->_method[$key])){
$routeFound = true;
$useMethod = $this->_method[$key];
new $useMethod();
}
else{
$routeFound = true;
call_user_func($this->_method[$key]);
}
}
}
if(!$routeFound){
http_response_code(404);
require_once 'pages/404.php';
}
}
}
?>
Helaas kan ik met deze code alleen een pagina url aanmaken zoals '/contact', '/about' etc. Ik ben nu zo ver met het project dat ik een pagina heb gemaakt voor een product, dit is dus een pagina met de product details van 1 specifiek product. Ik weet alleen niet hoe ik het voor elkaar krijg om een url als '/product/{id}' te maken aangezien ik via de code niet zomaar bijvoorbeeld een variabel kan meegeven. Ik maak namelijk routes aan met $route->add('/contact', function(){}); Ik hoop graag dat iemand me kan helpen :)
Edit:
Code-tags toegevoegd.
Gewijzigd op 07/02/2018 18:08:34 door - Ariën -
Nog wat anders: Na die preg_match() zal linksom of rechts $routeFound = true worden. Je kunt 'm dus een niveautje omhoog halen. Scheelt je weer een regel.
Voorzetje met params in constructor of aan te roepen functie, en nog wat andere tweaks:
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
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
<?php
class Route
{
private $_uri = array();
private $_method = array();
/*
* Builds a collection of internal URL's to look for
* @param type $uri
*/
public function add($uri, $method = null)
{
$this->_uri[] = '/' . trim($uri, '/');
if($method != null){
$this->_method[] = $method;
}
}
public function submit()
{
$uriGetParam = isset($_GET['uri']) ? '/' . $_GET['uri'] : '/';
$routeFound = false;
foreach($this->_uri as $key => $value){
if($routeFound = preg_match("#^$value$#",$uriGetParam,$params)){
if(is_string($this->_method[$key])){
$useMethod = $this->_method[$key];
new $useMethod($params);
}
else{
call_user_func_array($this->_method[$key],$params);
}
break;
}
}
if(!$routeFound){
http_response_code(404);
require_once 'pages/404.php';
}
}
}
?>
class Route
{
private $_uri = array();
private $_method = array();
/*
* Builds a collection of internal URL's to look for
* @param type $uri
*/
public function add($uri, $method = null)
{
$this->_uri[] = '/' . trim($uri, '/');
if($method != null){
$this->_method[] = $method;
}
}
public function submit()
{
$uriGetParam = isset($_GET['uri']) ? '/' . $_GET['uri'] : '/';
$routeFound = false;
foreach($this->_uri as $key => $value){
if($routeFound = preg_match("#^$value$#",$uriGetParam,$params)){
if(is_string($this->_method[$key])){
$useMethod = $this->_method[$key];
new $useMethod($params);
}
else{
call_user_func_array($this->_method[$key],$params);
}
break;
}
}
if(!$routeFound){
http_response_code(404);
require_once 'pages/404.php';
}
}
}
?>
Gewijzigd op 07/02/2018 19:15:29 door Rob Doemaarwat
Bedoelde je met het eruit prummelen van het id bijvoorbeeld door op de product pagina dit te doen?
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
$uri = $_SERVER['REQUEST_URI'];
$pin = explode('/', $uri);
$id = $pin[2];
$query->prepare("SELECT * FROM `table` WHERE `id`=$id");
$query->execute();
?>
$uri = $_SERVER['REQUEST_URI'];
$pin = explode('/', $uri);
$id = $pin[2];
$query->prepare("SELECT * FROM `table` WHERE `id`=$id");
$query->execute();
?>
Toevoeging op 07/02/2018 19:38:31:
Oh en dan had ik nog een vraagje, omdat ik nu een stap dieper ga met de url, hoe krijg ik het dan voor elkaar om de styling weer terug te krijgen? Nu gebruik ik Maar dat komt te vervallen omdat er iets extra's in de url erbij zit.
En niet $_SERVER['DOCUMENT_ROOT'], want CLI-script (crons bijv.) gaan dan moeilijk doen, omdat ze het pad niet kunnen vinden vanaf waar ze uitgevoerd worden.
Voor voor zover ik zie zal het eigenlijk geen probleem zijn als de URl wordt aangepast. Er wordt met include ook gekeken naar de fysieke plek op de server waar je script in draait, en die verandert nooit.
Gewijzigd op 07/02/2018 21:36:32 door - Ariën -
Jorn Reed op 07/02/2018 19:31:10:
Bedoelde je met het eruit prummelen van het id bijvoorbeeld door op de product pagina dit te doen?
In mijn voorbeeld geef ik de params uit de URL (de match uit preg_match) mee in de constructor of callable voor de afhandeling van de pagina. Dus bijvoorbeeld:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
$router->add('/product/(\d+)',function($match,$id){
//$match = complete URL match
//$id = ID uit de URL
});
//of:
class Pagina{
public function __construct($params){
//ID = $params[1]
}
}
//$match = complete URL match
//$id = ID uit de URL
});
//of:
class Pagina{
public function __construct($params){
//ID = $params[1]
}
}
Let trouwens op met je letterlijke $id in de query. Nu dwingt de router min of meer af dat het om een numeriek waarden gaat (\d+ in de reg-ex), maar als je dit een keer vergeet, of ook een andere manier van aanroepen mogelijk maakt, dan kun je hiermee de deur wagenwijd open zetten voor SQL injectie.
Gewijzigd op 07/02/2018 22:06:51 door Rob Doemaarwat
Met zaken als ?uri=$1 vervuil je in wezen de namespace van $_GET, die eigenlijk volledig transparant zou moeten zijn (what you see is what you have/get).
:p