Yes, you have a conflict.
- Both your
.htaccess
rules have exactly the same conditions, so the first one is always going to win. The second is never going to be executed.
- Your URL structure is ambiguous.
You need to take a step back, before trying to write any code, how would you resolve the following URLs:
https://example.com/home
https://example.com/article
https://example.com/foo
How do you know that home
should resolve to ?p=home
and article
should resolve to ?page=article
? What about foo
? You can only "see" what's in the URL.
You need to either:
- Have some discernible difference between the URLs, so you know how to rewrite it. For example:
example.com/p/home
vs example.com/pg/home
If the number of URLs rewritten to ?p=
(or ?page=
) is limited then you can literally list the URL patterns in your directive. And everything else goes to ?page=
(or ?p=
). For example:
RewriteRule ^(home|about)$ index.php?p=$1 [L]
:
RewriteRule ^([^/]+)$ index.php?page=$1 [L]
Rewrite everything to a single URL parameter (eg. ?page=
) and decide in your PHP how the page should be served. This would seem to be the more logical solution since you are rewriting to index.php
in both scenarios anyway and you don't want to keep having to edit .htaccess
. This could also handle the additional tab
"parameter".
The additional "tab" parameter
If all URLs that have a second path segment should be rewritten to ?page=
then that could be a "discernable" difference. However, that currently fails when the second path segment is omitted, as in /article
. How should this be handled?
the files to ?page=
are into a sub-directory, and the URL could be this: https://example.com/news-folder/article
Your question made no reference to a subdirectory. This would be enough to differentiate the "type" of URLs and to be able to rewrite the URLs differently.
For example:
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]
The last two rules could be combined if you are OK having an empty tab
parameter. eg. example.com/news-folder/article
would be rewritten example.com/index.php?page=article&tab=
. As it stands, the directives are separate, so the tab
parameter is not present at all when /2
(for example) is not appended.
UPDATE: The filesystem checks (for static resources and to prevent a rewrite loop) could be omitted entirely if you are more restrictive with the regex you use to target your article pages. For example:
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]
This just means that your URLs to your pages cannot contain .
(dot). You could be more restrictive and only allow word characters (plus hyphen) and change [^/.]+
to [\w-]+
. This then allows article names that only consist of the characters: 0-9
, a-z
, A-Z
, _
and -
.
You can make the subdirectory /news-folder
entirely generic and match any subdirectory. For example:
RewriteRule ^\w+/(\w+)$ index.php?page=$1 [L]
Now, any request for /<something>/article
would be rewritten to index.php?page=article
.
?p=
and some "first path segments" to?page=
. That's the primary conflict that needs resolving before the additionaltab
parameter.