web-dev-qa-db-fra.com

Plusieurs règles pour réécrire l'URL

Pourquoi les deux règles ne fonctionnent pas ensemble et comment puis-je résoudre ce problème? Seul le premier fonctionne ... Je pense qu'il y a un conflit entre les deux règles, mais je n'ai pas encore trouvé de solution

?p= est la chaîne de requête que j'utilise pour accéder aux fichiers qui se trouvent dans le répertoire principal de mon site Web, et ?page= correspond à un sous-répertoire.

Mes URL actuelles sont:

https://example.com/?p=home
https://example.com/?page=article
https://example.com/?page=article&tab=2

Et je veux que ça devienne:

https://example.com/home
https://example.com/article
https://example.com/article/2

.htaccess:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ index.php?p=$1 [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ index.php?page=$1 [L]
3
Derp Dee Derp

Oui, vous avez un conflit.

  • Vos deux règles .htaccess ont exactement les mêmes conditions, donc la première va toujours gagner. La seconde ne sera jamais exécutée.
  • Votre structure d'URL est ambiguë.

Avant d'essayer d'écrire du code, vous devez prendre du recul. Comment résolvez-vous les URL suivantes:

  • https://example.com/home
  • https://example.com/article
  • https://example.com/foo

Comment savez-vous que home devrait se résoudre en ?p=home et article devrait se résoudre en ?page=article? Qu'en est-il de foo? Vous pouvez uniquement "voir" le contenu de l'URL.

Vous devez soit:

  • Ayez une différence perceptible entre les URL afin de savoir comment le réécrire. Par exemple: example.com/p/home vs example.com/pg/home
  • Si le nombre d'URL réécrites dans ?p= (ou ?page=) est limité, vous pouvez répertorier littéralement les modèles d'URL dans votre directive. Et tout le reste va à ?page= (ou ?p=). Par exemple:

    RewriteRule ^(home|about)$ index.php?p=$1 [L]
    :
    RewriteRule ^([^/]+)$ index.php?page=$1 [L]
    
  • Réécrivez tout dans un paramètre d'URL unique (par exemple, ?page=) et décidez dans votre PHP comment la page doit être. servi. Cela semblerait être la solution la plus logique puisque vous êtes en train de réécrire index.php dans les deux scénarios et que vous ne voulez plus avoir à modifier .htaccess. Cela pourrait également gérer le paramètre tab supplémentaire.

Le paramètre "tab" supplémentaire

Si toutes les URL comportant un second segment de chemin doivent être réécrites dans ?page=, il pourrait alors s'agir d'une différence "discernable". Cependant, cela échoue actuellement lorsque le deuxième segment de chemin est omis, comme dans /article. Comment cela devrait-il être géré?

les fichiers vers ?page= se trouvent dans un sous-répertoire et l'URL pourrait être ceci: https://example.com/news-folder/article

Votre question ne fait aucune référence à un sous-répertoire. Cela suffirait à différencier le "type" d'URL et à pouvoir réécrire les URL différemment.

Par exemple:

RewriteEngine On

# Stop processing if the request looks like it maps to a physical resource
RewriteCond %{REQUEST_URI} \.(?:gif|jpg|png|css|js)$ [OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]

# Single path segment rewrite to ?p=
RewriteRule ^([^/]+)$ index.php?p=$1 [L]

# Requests for files in the subdirectory rewrite to ?page=
RewriteRule ^news-folder/([^/]+)$ index.php?page=$1 [L]

# Requests for files in the subdirectory with additional numeric "tab"
RewriteRule ^news-folder/([^/]+)/(\d+)$ index.php?page=$1&tab=$2 [L]

Les deux dernières règles peuvent être combinées si vous êtes OK avec un paramètre vide tab. par exemple. example.com/news-folder/article serait réécrit example.com/index.php?page=article&tab=. Les directives étant distinctes, le paramètre tab n'est pas présent du tout lorsque /2 (par exemple) n'est pas ajouté.

PDATE: Les vérifications du système de fichiers (pour les ressources statiques et pour empêcher une boucle de réécriture) peuvent être totalement omises si vous êtes plus restrictif avec la regex que vous utilisez pour cibler vos pages d'article. Par exemple:

RewriteEngine On

# Single path segment rewrite to ?p=
RewriteRule ^([^/.]+)$ index.php?p=$1 [L]

# Requests for files in the subdirectory rewrite to ?page=
RewriteRule ^news-folder/([^/.]+)$ index.php?page=$1 [L]

# Requests for files in the subdirectory with additional numeric "tab"
RewriteRule ^news-folder/([^/.]+)/(\d+)$ index.php?page=$1&tab=$2 [L]

Cela signifie simplement que vos URL vers vos pages ne peuvent pas contenir . (point). Vous pourriez être plus restrictif et n'autoriser que les caractères Word (plus un trait d'union) et changer [^/.]+ en [\w-]+. Cela autorise ensuite les noms d’article composés uniquement des caractères: 0-9, a-z, A-Z, _ et -.

Vous pouvez rendre le sous-répertoire /news-folder entièrement générique et faire correspondre tout sous-répertoire. Par exemple:

RewriteRule ^\w+/(\w+)$ index.php?page=$1 [L]

Désormais, toute demande de /<something>/article sera réécrite dans index.php?page=article.

2
MrWhite