2 Slash dans l'URL

Par Théo Benoit, il y a 7 ans


Bonjour,

J'ai crée un mini-framework à l'aide de la base que nous a fournis Grafikart, avec le Router.

J'ai cependant un problème sur le serveur, l'url me met 2 slash : www.url.com//{route}

Voici mon htaccess :

# Rediriger toutes les urls sur "index.php?url=URL" RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php?url=$1 [QSA,L] RewriteCond %{HTTP:X-Forwarded-Proto} !https RewriteRule (.*) https://www.domain.com/$1 [R=301,L]

Router.php :

<?php namespace App\Router; /** * Gère les routes de notre application */ class Router { /** * Url passé en paramètre * @var string */ private static $url; /** * Tableau contenant toutes les routes de notre application (GET, POST, ...) * @var array */ private static $routes = []; /** * Routes portant un nom * @var array */ private static $namedRoutes = []; /** * Initialisation de la classe router * @return void */ public static function init() { self::$url = $_GET['url']; } /** * Renvoie une page en GET * @param string * @param function * @return route */ public static function get($path, $callable, $name = null) { return self::add($path, $callable, $name, 'GET'); } /** * Renvoie une page en POST * @param string * @param function * @return route */ public static function post($path, $callable, $name = null) { return self::add($path, $callable, $name, 'POST'); } /** * Ajouter une route à notre router * @param string * @param function * @param string 'GET, POST, ...' */ private static function add($path, $callable, $name, $method) { $route = new Route($path, $callable); self::$routes[$method][] = $route; if ($name) { self::$namedRoutes[$name] = $route; } return $route; } /** * Lance le routing * @return function */ public static function run() { if (!isset(self::$routes[$_SERVER['REQUEST_METHOD']])) { throw new RouterException('REQUEST_METHOD doesn\'t exist'); } foreach(self::$routes[$_SERVER['REQUEST_METHOD']] as $route) { if ($route->match(self::$url)) { return $route->call(); } } throw new RouterException('No matching routes'); } /** * Retourne l'URL d'une route nommée * @param string * @param array * @return string */ public static function url($name, $params = []) { if (!isset(self::$namedRoutes[$name])) { throw new RouterException("No routes matches this name '$name'."); } return self::$namedRoutes[$name]->getUrl($params); } }

Route.php :

<?php namespace App\Router; /** * Une route */ class Route { /** * Chemin de la route * @var string */ private $path; /** * Fonction anonyme * @var function */ private $callable; /** * Correspondances avec une route du router * @var array */ private $matches = []; /** * Paramètres de la route * @var array */ private $params = []; /** * @param string * @param function */ public function __construct($path, $callable) { $this->path = trim($path, '/'); $this->callable = $callable; } /** * Permet d'ajouter des conditions à la route * @param param paramètre où faire la condition * @param regex expression régulière * @return route */ public function with($param, $regex) { $this->params[$param] = str_replace('(', '(?:', $regex); return $this; } /** * On check si la route match l'url * @param url * @return boolean */ public function match($url) { $url = trim($url, '/'); $path = preg_replace_callback('#{([\w]+)}#', [$this, 'paramMatch'], $this->path); $regex = "#^$path$#i"; if (!preg_match($regex, $url, $matches)) { return false; } array_shift($matches); $this->matches = $matches; return true; } /** * On teste si le paramètre "match" avec ce qu'on a dans $this->params * @param match * @return regex */ private function paramMatch($match) { if (isset($this->params[$match[1]])) { return '(' . $this->params[$match[1]] . ')'; } return '([^/]+)'; } /** * On appelle la fonction passé en paramètre pour la route (controller ou anonyme) * @return function */ public function call() { if (is_string($this->callable)) { $params = explode('@', $this->callable); $controller = "App\\Controller\\" . $params[0]; $controller = new $controller(); return call_user_func_array([$controller, $params[1]], $this->matches); } else { return call_user_func_array($this->callable, $this->matches); } } /** * Retourne l'URL de la route avec les paramètres donnés * @param array * @return string */ public function getUrl($params) { $path = $this->path; foreach($params as $k => $v) { $path = str_replace("{" . $k . "}", $v, $path); } if (isset($_SERVER['HTTPS'])) { return 'https://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']) . '/' . $path; } return 'http://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']) . '/' . $path; } }

Je viens vers vous car j'ai tout essayé pendant quelques heures, mais je n'arrive pas à règler le problème. Le site fonctionne correctement à part ces 2 slahs !!

Merci beaucoup,
Théo.

2 réponses

Huggy, il y a 7 ans

Dans la méthode getUrl, la fonction dirname($_SERVER['PHP_SELF']) renvoie un slash au début mais pas à la fin, tu en rajoutes un OK
mais dans la cas où tu es à la racine du site, dirname renvoie quand même le slash de début (anti-slash sous windows)
donc tu en a deux

il faut soit traiter le cas particulier de la racine, soit utiliser une constante BASE_URL qui remplacera le dirname
define('BASE_URL', '/'); // http://monsite.com/
ou
define('BASE_URL', '/monsite/'); //wamp http://localhost/monsite/

return 'https://' . $_SERVER['HTTP_HOST'] . BASE_URL . $path;

Théo Benoit, il y a 7 ans

Merci beaucoup !!

Je ne savais pas du tout cela, et étant donné qu'en local ça ne me faisait pas pareil ^^
En tout cas merci, c'est très gentil !

Bonne soirée,
Cordialement.