Routes

Grace à la réécriture d'adresse, nous pouvons faire croire à l'utilisateur qu'il existe un fichier afficher-personne-1. En réalité, c'est le fichier index.php qui est ouvert.

Notre travail consiste à récupérer l'uri envoyée par l'utilisateur et d'orienter vers la bonne ressource. C'est à dire vers le bon dossier (controller) et le bon fichier (action).

L’information qui fait correspondre une uri à un controller et une action est appelée une route.

MéthodeRoute

Exemple de routes :

1
//          [path, name, [controller, action]]
2
$routes = [];
3
$routes[] = ['/', 'home.index', ['home', 'index']];
4
$routes[] = ['/personnes', 'personne.index', ['personne', 'index']];
5
$routes[] = ['/ajouter-personne', 'personne.create', ['personne', 'create']];
6
$routes[] = ['/afficher-personne-{id}', 'personne.show', ['personne', 'show']];
7
$routes[] = ['/modifier-personne-{id}', 'personne.update', ['personne', 'update']];
8
$routes[] = ['/supprimer-personne-{id}', 'personne.delete', ['personne', 'delete']];
9

path : uri de la ressource. {id} indique qu'il y a un paramètre appelé id

name : clé unique de la route

controller : dossier où se trouve réellement la ressource

action : nom du fichier de la ressource sans son extension

Méthodeuri et root

Pour retrouver la route en fonction de l'uri, nous avons besoin de récupérer l'uri d'origine.

1
$uri = parse_url($_SERVER['REQUEST_URI'])['path'];

normalement le fichier index.php se trouve à la racine de votre site.

Dans le cas contraire il faut en tenir compte.

Il faut récupérer l'éventuel chemin (root) entre localhost et public.

1
$root = dirname($_SERVER['PHP_SELF']);
2
$root = $root == '\\' ? '' : $root;

on supprime le $root de $uri

1
$uri = str_replace($root, '', $uri);

MéthodegetRoute($routes, $uri)

La fonction getRoute() permet de retourner la route correspondant à l'uri.

Le principe est de créer un pattern qui permet de vérifier que l'uri a la même structure qu'une des routes.

1
function getRoute($routes, $uri)
2
{
3
    foreach ($routes as $route) {
4
        // pattern pour retrouver les paramettres : -{id}-{slug} --> id et slug
5
        $pattern = '/-{([^}]+)}/';
6
7
        // pattern verifiant le lien entre path et uri : 
8
        // à partir de : /afficher-personne-{id}-{slug}
9
        // on crée le pattern : /afficher-personne-[^-]+-[^-]+
10
        // permet de matcher avec : /afficher-personne-1-dupont
11
        $pattern = '/^\\' . preg_replace($pattern, '-[^-]+', $route[0]) . '$/';
12
13
        if (preg_match($pattern, $uri))
14
            return $route;
15
    }
16
    return null;
17
}

getRoute : array_reduce recherche et conserve la route dont le path correspond à l'uri.

generateUri : retourne le path de la route correspondant à la clé avec les paramètres.

MéthodegetParams($key)

La fonction getParams() permet de retourner la valeur d'un paramètre de l'uri.

1
function getParams($key)
2
{
3
    global $route;
4
    global $uri;
5
    // récupère la partie fixe de la route
6
    $pattern = '/-{([^}]+)}/';
7
    $fixe = preg_replace($pattern, '', $route[0]);
8
9
    // récupère les paramètres du path de la route
10
    preg_match_all($pattern, $route[0] ?? '', $keys);
11
12
    // récupère la partie variable de l'uri
13
    $variables = str_replace($fixe, '', $uri);
14
15
    // récupère les valeurs des paramètres de l'uri
16
    $pattern = "/-([^-]+)/";
17
    preg_match_all($pattern, $variables, $values);
18
19
    // génére un tableau associatif avec les keys et les values
20
    $params = array_combine($keys[1], $values[1]);
21
22
    // on retourne la valeur correspondant à la clé
23
    return $params[$key] ?? null;
24
}

Méthoderoute()

La fonction route() permet de générer l'uri à partir de la clé de la route.

route('personne.index') => '/personnes'

route('personne.show', ['id'=>1]) => '/afficher-personne-1'

1
function route(string $name, array $vars = [])
2
{
3
    global $routes;
4
    global $root;
5
6
    foreach ($routes as $route) {
7
8
        if ($route[1] == $name) {
9
10
            foreach ($vars as $key => $val) {
11
                $route[0] = str_replace('{' . $key . '}', $val, $route[0]);
12
            }
13
            return $root . $route[0];
14
        }
15
    }
16
17
    return '';
18
}

ExemplePour tester

Modifiez le fichier index.php

1
<h1>Récupération des informations nécessaire à la gestion des routes</h1>
2
<?php
3
4
// on récupère l'uri réécrite
5
$uri = parse_url($_SERVER['REQUEST_URI'])['path'];
6
// affichage de $uri
7
echo "<b>uri depuis localhost</b> : $uri <br/>";
8
9
// normalement index.php se trouve à la racine de votre site
10
// dans le cas contraire il faut en tenir compte
11
// on récupère l'éventuel chemin entre localhost et public
12
$root = dirname($_SERVER['PHP_SELF']);
13
$root = $root == '\\' ? '' : $root;
14
// affichage de $root
15
echo "<b>root éventuelle</b> : $root <br/>";
16
17
// on supprime le $root de $uri
18
$uri = str_replace($root, '', $uri);
19
// affichage de $uri sans le $root
20
echo "<b>uri sans le root</b> : $uri <br/>";
21
22
// Routes du site
23
$routes = [];
24
// $routes[] = [path, name, [controller, action]];
25
$routes[] = ['/', 'home.index', ['home', 'index']];
26
// path : uri de la ressource. {id} indique qu'il y a un paramètre appelé id
27
// name : clé unique de la route
28
// controller : dossier où se trouve réellement la ressource
29
// action : nom du fichier de la ressource sans son extension
30
$routes[] = ['/personnes', 'personne.index', ['personne', 'index']];
31
$routes[] = ['/ajouter-personne', 'personne.create', ['personne', 'create']];
32
$routes[] = ['/afficher-personne-{id}', 'personne.show', ['personne', 'show']];
33
$routes[] = ['/modifier-personne-{slug}', 'personne.update', ['personne', 'update']];
34
$routes[] = ['/supprimer-personne-{id}-{slug}', 'personne.delete', ['personne', 'delete']];
35
36
// permet de rechercher la route correspondant à l'uri
37
function getRoute($routes, $uri)
38
{
39
    foreach ($routes as $route) {
40
        // pattern pour retrouver les paramettres : -{id}-{slug} --> id et slug
41
        $pattern = '/-{([^}]+)}/';
42
43
        // pattern verifiant le lien entre path et uri : 
44
        // à partir de : /afficher-personne-{id}-{slug}
45
        // on crée le pattern : /afficher-personne-[^-]+-[^-]+
46
        // permet de matcher avec : /afficher-personne-1-dupont
47
        $pattern = '/^\\' . preg_replace($pattern, '-[^-]+', $route[0]) . '$/';
48
49
        if (preg_match($pattern, $uri))
50
            return $route;
51
    }
52
    return null;
53
}
54
$route = getRoute($routes, $uri);
55
56
// affichage de la route
57
echo '<b>route :</b><pre>';
58
var_dump($route);
59
echo '</pre><br/>';
60
61
// permet de retourner la valeur d'un paramètre
62
function getParams($key)
63
{
64
    global $route;
65
    global $uri;
66
    // récupère la partie fixe de la route
67
    $pattern = '/-{([^}]+)}/';
68
    $fixe = preg_replace($pattern, '', $route[0]);
69
70
    // récupère les paramètres du path de la route    
71
    preg_match_all($pattern, $route[0] ?? '', $keys);
72
73
    // récupère la partie variable de l'uri
74
    $variables = str_replace($fixe, '', $uri);
75
76
    // récupère les valeurs des paramètres de l'uri
77
    $pattern = "/-([^-]+)/";
78
    preg_match_all($pattern, $variables, $values);
79
80
    // génére un tableau associatif avec les keys et les values
81
    $params = array_combine($keys[1], $values[1]);
82
83
    // on retourne la valeur correspondant à la clé
84
    return $params[$key] ?? null;
85
}
86
echo "<b>id = </b> " . getParams('id') . "<br/>";
87
echo "<b>slug = </b> " . getParams('slug') . "<br/>";
88
89
90
// permet de générer l'uri à partir de la clé de la route
91
// route('personne.index') => '/personnes'
92
// route('personne.show', ['id'=>1]) => '/afficher-personne-1'
93
function route(string $name, array $vars = [])
94
{
95
    global $routes;
96
    global $root;
97
98
    foreach ($routes as $route) {
99
100
        if ($route[1] == $name) {
101
102
            foreach ($vars as $key => $val) {
103
                $route[0] = str_replace('{' . $key . '}', $val, $route[0]);
104
            }
105
            return $root . $route[0];
106
        }
107
    }
108
109
    return '';
110
}
111
112
?>
113
114
<nav>
115
    <ul>
116
        <li>
117
            <a href='<?= route('home.index') ?>'>
118
                route('home.index')
119
            </a>
120
        </li>
121
        <li>
122
            <a href='<?= route('personne.index') ?>'>
123
                route('personne.index')
124
            </a>
125
        </li>
126
        <li>
127
            <a href='<?= route('personne.show', ['id' => 1]) ?>'>
128
                route('personne.show', ['id' => 1])
129
            </a>
130
        </li>
131
        <li>
132
            <a href='<?= route('personne.update', ['slug' => 'dupont']) ?>'>
133
                route('personne.update', ['slug' => 'dupont'])
134
            </a>
135
        </li>
136
        <li>
137
            <a href='<?= route('personne.delete', ['id' => 3, 'slug' => 'dupont']) ?>'>
138
                route('personne.delete', ['id' => 3, 'slug' => 'dupont'])
139
            </a>
140
        </li>
141
142
    </ul>
143
</nav>