web-dev-qa-db-fra.com

Réécriture d'URL avec PHP

J'ai une URL qui ressemble à:

url.com/picture.php?id=51

Comment ferais-je pour convertir cette URL en:

picture.php/Some-text-goes-here/51

Je pense que WordPress fait la même chose.

Comment puis-je créer des URL conviviales en PHP?

131
Jazerix

Si vous voulez seulement changer la route pour picture.php, alors ajouter une règle de réécriture dans .htaccess répondra à vos besoins, mais si vous voulez que l'URL soit réécrite comme dans Wordpress, alors PHP est la solution. Voici un exemple simple pour commencer.

Structure des dossiers

Il y a deux fichiers nécessaires dans le dossier racine, .htaccess et index.php, et il serait bien de placer le reste des fichiers .php dans un dossier séparé, comme inc/.

root/
  inc/
  .htaccess
  index.php

. htaccess

RewriteEngine On
RewriteRule ^inc/.*$ index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,L]

Ce fichier contient quatre directives:

  1. RewriteEngine - active le moteur de réécriture
  2. RewriteRule - refuse l'accès à tous les fichiers du dossier inc/, redirige tout appel de ce dossier vers index.php
  3. RewriteCond - autorise un accès direct à tous les autres fichiers (comme les images, les CSS ou les scripts)
  4. RewriteRule - redirige n'importe quoi d'autre vers index.php

index.php

Puisque tout est maintenant redirigé vers index.php, il sera déterminé si l’URL est correcte, tous les paramètres sont présents et si le type de paramètres est correct.

Pour tester l'URL, nous avons besoin d'un ensemble de règles, et le meilleur outil pour cela est une expression régulière. En utilisant des expressions régulières, nous allons tuer deux mouches d'un coup. Url, pour réussir ce test, il faut que tous les paramètres requis soient testés sur les caractères autorisés. Voici quelques exemples de règles.

$rules = array( 
    'picture'   => "/picture/(?'text'[^/]+)/(?'id'\d+)",    // '/picture/some-text/51'
    'album'     => "/album/(?'album'[\w\-]+)",              // '/album/album-slug'
    'category'  => "/category/(?'category'[\w\-]+)",        // '/category/category-slug'
    'page'      => "/page/(?'page'about|contact)",          // '/page/about', '/page/contact'
    'post'      => "/(?'post'[\w\-]+)",                     // '/post-slug'
    'home'      => "/"                                      // '/'
);

Suivant est de préparer la demande uri.

$uri = rtrim( dirname($_SERVER["SCRIPT_NAME"]), '/' );
$uri = '/' . trim( str_replace( $uri, '', $_SERVER['REQUEST_URI'] ), '/' );
$uri = urldecode( $uri );

Maintenant que nous avons la requête uri, la dernière étape consiste à tester uri sur des règles d’expression régulière.

foreach ( $rules as $action => $rule ) {
    if ( preg_match( '~^'.$rule.'$~i', $uri, $params ) ) {
        /* now you know the action and parameters so you can 
         * include appropriate template file ( or proceed in some other way )
         */
    }
}

La correspondance réussie, puisque nous utilisons des sous-modèles nommés dans regex, remplit le tableau $params de la même manière que PHP remplit le tableau $_GET. Toutefois, lorsque vous utilisez une URL dynamique, le tableau $_GET est rempli sans vérification des paramètres.

 /picture/some+text/51

 Tableau 
 (
 [0] =>/image/du texte/51 
 [text] => du texte 
 [1] => du texte 
 [id] => 51 
 [2] => 51 
) 
 
 picture.php? text = some + text & id = 51 
 
 Tableau 
 (
 [text] => du texte 
 [id] => 51 
) 

Ces quelques lignes de code et une connaissance de base des expressions régulières suffisent pour créer un système de routage solide.

source complète

define( 'INCLUDE_DIR', dirname( __FILE__ ) . '/inc/' );

$rules = array( 
    'picture'   => "/picture/(?'text'[^/]+)/(?'id'\d+)",    // '/picture/some-text/51'
    'album'     => "/album/(?'album'[\w\-]+)",              // '/album/album-slug'
    'category'  => "/category/(?'category'[\w\-]+)",        // '/category/category-slug'
    'page'      => "/page/(?'page'about|contact)",          // '/page/about', '/page/contact'
    'post'      => "/(?'post'[\w\-]+)",                     // '/post-slug'
    'home'      => "/"                                      // '/'
);

$uri = rtrim( dirname($_SERVER["SCRIPT_NAME"]), '/' );
$uri = '/' . trim( str_replace( $uri, '', $_SERVER['REQUEST_URI'] ), '/' );
$uri = urldecode( $uri );

foreach ( $rules as $action => $rule ) {
    if ( preg_match( '~^'.$rule.'$~i', $uri, $params ) ) {
        /* now you know the action and parameters so you can 
         * include appropriate template file ( or proceed in some other way )
         */
        include( INCLUDE_DIR . $action . '.php' );

        // exit to avoid the 404 message 
        exit();
    }
}

// nothing is found so handle the 404 error
include( INCLUDE_DIR . '404.php' );
55
Danijel

c'est un fichier .htaccess qui transmet presque tout à index.php

# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_URI} !-l
RewriteCond %{REQUEST_FILENAME} !\.(ico|css|png|jpg|gif|js)$ [NC]
# otherwise forward it to index.php
RewriteRule . index.php

alors, c’est à vous d’analyser $ _SERVER ["REQUEST_URI"] et d’acheminer vers picture.php ou autre chose

5
Luca Rocchi

PHP n’est pas ce que vous cherchez, consultez mod_rewrite

3
rauchmelder

Bien que nous y ayons déjà répondu, l'auteur souhaite créer une application de type contrôleur frontal, mais je publie une règle littérale pour le problème posé. si quelqu'un a le même problème.

RewriteEngine On
RewriteRule ^([^/]+)/([^/]+)/([\d]+)$ $1?id=$3 [L]

Ci-dessus devrait fonctionner pour url picture.php/Some-text-goes-here/51. sans utiliser un index.php comme une application de redirection.

1
Abhishek Gurjar