Mod_rewrite for single.php - .htaccess

I'd like to use mod_rewrite to show pretty urls in my urls:
Instead of
.../juegos/plants-vs-zombies/?play=jugar
change to
.../juegos/plants-vs-zombies/jugar/
And
.../juegos/ddtank/?play=full
change to
.../juegos/ddtank/full/
I use the file "single.php" with this code:
$url = (isset($_SERVER['HTTPS']) ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$parts = parse_url($url);
parse_str($parts['query'], $query);
$parametro = $query['play'];
if ($parametro == 'jugar')
{
include( get_template_directory() . '/single-play.php');
}
else if ($parametro == 'full')
{
include( get_template_directory() . '/single-full.php');
}
And in .htaccess I have this:
RewriteEngine On
RewriteCond %{QUERY_STRING} (^|&)play=jugar($|&)
RewriteRule ^(.*)/$ /jugar/?&%{QUERY_STRING}
But when I try to get the url with /jugar/ and /full/ at the end of the url, it displays an 404 error.
I don't know what else to do. I hope you can help me.

Sounds pretty straight forward to me:
RewriteEngine on
RewriteRule ^/?juegos/plants-vs-zombies/jugar/?$ /juegos/plants-vs-zombies/?play=1 [END]
For that to work the rewriting module has to be installed and enabled, obviously. The rule will work likewise in the http servers host configuration and in a dynamic configuration file (.htaccess). If you decide to use a dynamic configuration file, then you need to place that in the http hosts document root folder and enable its interpretation using the AllowOverride directive in the host configuration.
If you receive a http status 500 using the above rule ("server internal error") chances are that you operate a very old version of the apache http server. In that case try replacing the [END] flag with the [L] flag.
And a general hint: you should always prefer to place such rules inside the http servers (virtual) host configuration instead of using dynamic configuration files (.htaccess style files). Those files are notoriously error prone, hard to debug and they really slow down the server. They are only supported as a last option for situations where you do not have control over the host configuration (read: really cheap hosting service providers) or if you have an application that relies on writing its own rewrite rules (which is an obvious security nightmare).

what the browser sees /juegos/plants-vs-zombies/jugar/,
what the server sees ?play=juegos/plants-vs-zombies/jugar
after explode it changes to an Array ( [0] => juegos [1] => plants-vs-zombies/ [1] => jugar)
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ ?play=$1 [NC]
This to change$_GET['play'] to an array
$play = explode("/", $_GET['play']);
if(isset($_GET['play'])){
$play = explode("/", $_GET['play']);
//if you want to add `/` at the end
if(end($play) == ""){
array_pop($page);
}
}
Passing Query String Parameters in WordPress URL

Related

I need to redirect my dynamic URL to a clean and SEO friendly static URL using htaccess

I am a web developer. I have developed a news portal for my client. But the URLs of the articles are dynamic and I need to redirect it to a static URL for SEO purpose.
The current URL : https://example.com/single-post.php?id=1&category=news&title=this-is-a-title
Desired URL : https://example.com/news/this-is-a-title
Someone please help me.
I have wrote this :
RewriteCond %{QUERY_STRING} (?:^|&)id=(\d+)(?:&|$)
RewriteCond %{QUERY_STRING} (?:^|&)title=([^&]+)(?:&|$)
RewriteRule ^/?single-post\.php$ /%2/%1 [R=301]
RewriteRule ^/?(.*)/(\d+)$ single-post.php?title=$1&id=$2 [END]
But the URL output is not what I expected. It is like :
https://example.com/this-is-title/?id=1&title=this-is-title
The only title came first without the id and then the old format came again after the slash. I can't understand what is going on here.
What you ask actually is not possible. There is no way for the rewriting module to somehow magically guess the numerical ID of that object you request. What you can actually do is publish URL in the style of https://example.com/news/1/this-is-a-title. Notice the ID in there, that is what is usally done. For that his should point you into the right direction:
RewriteEngine on
RewriteRule ^/?news/(\d+)/(.*)/?$ /single-post.php?id=$1&category=news&title=$2 [END]
Typically your application logic will only need the numerical ID of the requested object to fetch it from your database. So you typically can silently drop the title in the internal rewriting which makes things even more simple:
RewriteEngine on
RewriteRule ^/?news/(\d+) /single-post.php?id=$1&category=news [END]
In case you receive an internal server error (http status 500) using the rule above then chances are that you operate a very old version of the apache http server. You will see a definite hint to an unsupported [END] flag in your http servers error log file in that case. You can either try to upgrade or use the older [L] flag, it probably will work the same in this situation, though that depends a bit on your setup.
This rule will work likewise in the http servers host configuration or inside a dynamic configuration file (".htaccess" file). Obviously the rewriting module needs to be loaded inside the http server and enabled in the http host. In case you use a dynamic configuration file you need to take care that it's interpretation is enabled at all in the host configuration and that it is located in the host's DOCUMENT_ROOT folder.
And a general remark: you should always prefer to place such rules in the http servers host configuration instead of using dynamic configuration files (".htaccess"). Those dynamic configuration files add complexity, are often a cause of unexpected behavior, hard to debug and they really slow down the http server. They are only provided as a last option for situations where you do not have access to the real http servers host configuration (read: really cheap service providers) or for applications insisting on writing their own rules (which is an obvious security nightmare).
UPDATE:
in your comment to this answer you suggest to also do an explit redirection in case the target URL is used on the client side. Here is a variant of version 2 above which adds that redirection:
RewriteEngine on
RewriteCond %{QUERY_STRING} (?:^|&)id=(\d+)(?:&|$)
RewriteRule ^/?single-post\.php$ /news/%1 [R=301]
RewriteRule ^/?news/(\d+) /single-post.php?id=$1&category=news [END]
A variant of version 1 would look similar:
RewriteEngine on
RewriteCond %{QUERY_STRING} (?:^|&)id=(\d+)(?:&|$)
RewriteCond %{QUERY_STRING} (?:^|&)title=([^&]+)(?:&|$)
RewriteRule ^/?single-post\.php$ /news/%1/%2 [R=301]
RewriteRule ^/?news/(\d+) /single-post.php?id=$1&category=news [END]
Is is a good idea to start with a 302 redirection first. And only change that to a 301 redirection once everything works fine. That saves you from hassles with client side caching while you are still trying things out.

Rewrite all url index to subfolders

I have website with many subfolders and problem with duplicate content example: https://example.com/sub1/ and https://example.com/sub1/index.html. How to rewrite all to only subfolder see without index.
This probably is what you are looking for:
RewriteEngine on
RewriteRule ^/?(.*)index\.html /$1 [END]
That rule will work likewise in the http server's host configuration or in a dynamic configuration file (".htaccess") inside the host's DOCUMENT_ROOT. You should always prefer the first variant if possible for various reasons.
In case you receive back a server internal error (http status 500) using above rule changes are that you operate a very old version of the apache http server. You will see a definite references to an unsupported END flag in that case in your server's error log file. Try using the L flag instead. It might work the same, though that depends a bit on your actual setup.
Check this rule on top of your .htaccess file
RewriteEngine On
RewriteBase /
RewriteRule ^(.*)\/index\.(html|htm)$ /$1/ [R=301,L]

URL rewriting without knowing page title

I currently have links at my site like this:
http://www.domain.com/locations/locationProfile.php?locationID=22
I am hoping, for SEO purposes that I could change this to something like this:
http://www.domain.com/locations/southern-maryland
"Southern Maryland" is currently pulled from a mysql db as the location name for location ID 22. Is it even possible to get this into the URL when my site structure currently utilizes the less attractive first version?
You can't use htaccess to do this for you. It's possible to use a RewriteMap that you can define in your server config (can't define it in htaccess file), but it's far easier if you just do this in your locationProfile.php script.
You can detect if the request is made with the query string using the REQUEST_URI value:
if ( $_SERVER['REQUEST_URI'] == '/locations/locationProfile.php' &&
isset($_GET['locationID'])) {
// go into DB and extract the location name then redirect
header('Location: /locations/' . $location-name);
}
Then in your htaccess file in your document root):
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^locations/([^/]+)$ /locations/locationProfile.php?locationName=$1 [L,QSA]
And finally, make your php script look for the locationName parameter and server the proper page based on that instead of the ID.

Yii and Mod Rewrite: redirect to user language translated url

I'm developing a multilanguage web app with Yii.
I applied changes to hide the index.php, changed urlFormat to path and added to the url path a slug with the user language example /it/index.php /en/index.php etc...
The problem now is that I need to redirect automatically to a different url once the user chooses another language. For example:
http://localhost/~antonio/project/it/women
needs to redirect to:
http://localhost/~antonio/project/it/femme
I have been playing with htaccess with no luck at all. Here is the actual code:
Options +FollowSymLinks
IndexIgnore */*
RewriteEngine on
RewriteBase /~antonio/project/
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
#My redirection code (tried a good few more to no use apart from this)
RewriteRule ^it/women$ it/femme
I would really appreciate any help on this issue, as it is driving me mad.
Thanks
Edit::
I surrendered with mod_rewrite. I found another solution by adding this code to /layout/main.php:
<?php
$onurl = Yii::app()->getRequest()->requestUri;
if ($onurl == "/~antonio/project/it/women") {
$this->redirect("/~antonio/project/it/femme");
} elseif ($onurl == "/~antonio/project/it/men") {
$this->redirect("/~antonio/project/it/uomme");
}
Rinse and repeat per combination of language/word
This might not work without setting up a proper Virtual Host (so that instead of local urls like http://localhost/~antonio/project/it/women you have nice urls like http://project1.dev). But I would do that anyway, since it makes your dev environment nicer! (Here's a place to start).
Anyway, I would try this: just leave the .htaccess file set like you normally would for "path" style urls, and then just parse a $_GET['lang'] parameter using the UrlManager? So you would have a urlManager setup like this in your config.php:
'urlManager'=>array(
'urlFormat'=>'path', // use path style parameters
'showScriptName'=>false, // get rid of index.php
'rules'=>array(
// this parses out the first chunk of url into the "lang" GET parameter
'<lang:[\w\-]+>/<controller:[\w\-]+>/<action:[\w\-]+>'=>'<controller>/<action>',
)
)
This way a url like this http://project1.dev/it/controller/action will redirect to the "action" action in your Controller like normal (controller/action), but in your action $_GET['lang'] will now have the value of "it".
I hope that helps, it's kind of a shot in the dark. I'm not sure how you are actually triggering the different languages, so a $_GET parameter might not be helpful after all.
Found a way to do this in htaccess:
RewriteCond %{REQUEST_URI} ^/~antonio/project/it/donna/shoes/(.*)$
RewriteRule ^it/donna/shoes/(.*)$ /~antonio/project/it/donna/calzature/$1 [L,R]

RewriteRule variables blank

I have a couple of rewrite rules in htaccess. They work on one server but not another. My script is as follows (I've commented out how the urls look):
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !^/images/
#example.com/regions/fife/
RewriteRule ^regions/([A-Za-z0-9\-\+\']+)/?$ /regions.php?region=$1 [L]
#example.com/regions/fife/dunfermline
RewriteRule ^regions/([^/]+)/([^/]+)$ /regions.php?region=$1&town=$2 [L]
It returns two variables (region & town) I can manipulate in PHP, and throw up the appropriate content. I have a Rackspace server, and the script works perfectly, but on another server (Freedom2surf) it only works so far. It doesn't return the variables. I get a blank $_GET array...
Any ideas? F2S aren't giving me any clues, just that I should check my code. But if it works on another server, then what gives? Is it an Apache setting that is different?
I think you may be after the 'QSA' flag, which will append the query string from the original request to the redirected request, e.g:
#example.com/regions/fife/
RewriteRule ^regions/([A-Za-z0-9\-\+\']+)/?$ /regions.php?region=$1 [L,QSA]
This sounds like you have a mod_negotiation conflict here and you need to turn Multiviews off. Sometimes apache default configurations have Multiviews turned on by default. What that does is it will look at a request, say, /regions/1234 and mod_negotiation will notice that there is a file /regions.php and assume that the request is actually for that php file. It'll thus serve /regions.php/1234 and completely bypass mod_rewrite. You can use Options to turn it off. Just add this to the top of your htaccess file:
Options -Multiviews

Resources