I'm fairly new to this, hopefully you can help me fix this problem.
I have a URL structure that gets an id from a database and shows the url like this:
www.website.com/post.php?P=18
I would like to present the URL's as:
www.website.com/post/18
In my .htaccess file, I've altered it like so:
RewriteEngine on
RewriteRule ^post/(\w+)$ post.php?P=$1
I've read through a few posts about this here on SO but I can't seem to figure it out.
I followed this:
The Rule:
RewriteRule ^user/(\w+)/?$ user.php?id=$1
Pattern to Match:
^ Beginning of Input
user/ The REQUEST_URI starts with the literal string "user/"
(\w+) Capture any word characters, put in $1
/? Optional trailing slash "/"
$ End of Input
Substitute with:
user.php?id= Literal string to use.
$1 The first (capture) noted above.
Thank you!
Try with below,
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^post/(\w+)$ post.php?P=$1 [L]
I think it's important to share this kind of information for others that may be having the same issue so here goes.
The Problem:
[1] A link that looked like: www.example.com/news.php?P=1
The link should look like www.example.com/news/1
Then, the link would have to end up showing text instead of an ID. www.example.com/news/news-name
The solution
First, i had anchor tags that looked like this
It gave the first result in the URL [1]. To change it so it would present as a www.example.com/news/1, i had to do the following:
Create a htaccess file and fill it like this:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [NC]
### THIS IS AN EXAMPLE FOR MULTIPLE EXPRESSIONS ###
#RewriteRule ^news/([0-9]+)/([0-9a-zA-Z_-]+) news.php?P=$1&name=$2 [NC,L]
RewriteRule ^news/([0-9]+) news.php?P=$1 [NC,L]
And then, change the anchor tags to:
[1] Would be done now.
The challenge now was to use a slug instead of an ID. On the post creation page, I added the following PHP:
<?php
setlocale(LC_ALL, 'en_US.UTF8');
function slugit($str, $replace=array(), $delimiter='-') {
if ( !empty($replace) ) {
$str = str_replace((array)$replace, ' ', $str);
}
$clean = iconv('UTF-8', 'ASCII//TRANSLIT', $str);
$clean = preg_replace("/[^a-zA-Z0-9\/_|+ -]/", '', $clean);
$clean = strtolower(trim($clean, '-'));
$clean = preg_replace("/[\/_|+ -]+/", $delimiter, $clean);
return $clean;
}
?>
Then, on the news insertion page, I added: $slug = slugit("$entry1");, which would pass $entry1 = $_POST['title']; as the title of the page, but slugified. On the database for the news, i created a column to accommodate $slug as a permalink name.
Now to present the URL with the slug, I had to change the anchor tag to:
And on the htaccess, change RewriteRule ^news/([0-9]+) news.php?P=$1 [NC,L] to RewriteRule ^news/([0-9a-zA-Z_-]+) news.php?P=$1 [NC,L]
That's how I got it to work. I hope this will help people with similar problems fix theirs.
Related
I've seen numerous examples on how to do this with queries that have numbers (like foo.php?id=21). However, this redirect I'm after is for hundreds of URLs but they have the same pattern, although some key value pairs will have a %20 in them. Here are three examples, followed by what I need them to redirect to:
photo/search.php?keywords=foo to gallery/search/foo
photo/search.php?keywords=foo%20bar to gallery/search/foo-bar
photo/search.php?keywords=major%20foo%20bar to gallery/search/major-foo-bar
I'm just not sure how to do this for hundreds of URLs.
[edit - added below]
Here's what I have that is mostly working now:
# Recursively replace spaces with hyphens until there are none left
RewriteCond %{QUERY_STRING} ^([^\s%20]*)[\s%20]+(.*)$
RewriteRule ^(.+)$ $1?%1-%2 [E=NOSPACE:1]
# When there is no space make an external redirection
RewriteCond %{ENV:NOSPACE} =1
RewriteCond %{QUERY_STRING} ^keywords=([^&]+)$
RewriteRule ^photo/search\.php$ /gallery/search/%1? [L,R=301]
My new problem is that if there is more than one space, the second % sign is getting encoded too, so the redirected URL ends up being wrong. Example:
this: http://example.com/photo/search.php?keywords=some%20keywords%20here
goes to this: http://example.com/gallery/search/some-keywords%2520here
but it should go to this: http://example.com/gallery/search/some-keywords-here
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /photo/search\.php
RewriteCond %{QUERY_STRING} keywords=([^&]+)
RewriteRule ^/?photo/search.php$ /gallery/search/%1? [NE,R,L]
RewriteRule ^/?gallery/search/([^/]+)$ /photo/search.php?keywords=$1 [L]
Line 1 - 3 : check the request line (e.g., "GET /index.html HTTP/1.1"), the request path is /photo/search.php, and if contains the query string keywords=, redirect the request uri from /photo/search.php to /gallery/search/%1?, %1 is the back-reference to ([^&]+), and ? remove any query string.
Line 4: internal rewrite the URL from /gallery/search/([^/]+) to /photo/search.php?keywords=$1, $1 is the back reference to ([^/]+).
You may need some help from php script, if spaces detected from keywords, redirect to the dash one.
if (isset($_GET['keywords']) && stripos($_GET['keywords'], ' ') !== false) {
header('location: /gallery/search/' . urlencode(str_replace(' ', '-', $_GET['keywords'])));
exit;
}
My codebase is located in url.com/ with /public housing index.php and .htaccess, which the servers configured to point at for url.com
My .htaccess looks like this:
RewriteEngine on
ServerSignature On
Options +Indexes +FollowSymlinks +MultiViews
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !\.(js|ico|gif|jpg|png|css)$ /index.php
RewriteRule ^([-A-Za-z0-9]+)/([-A-Za-z0-9]+).([-A-Za-z0-9]+)$ index.php?module=$1&action=$2&return=$3
RewriteRule ^([-A-Za-z0-9]+).([-A-Za-z0-9]+)$ index.php?module=$1&action=index&return=$3
What I would like is the following URLS to get the following:
url.com/users/list.json equal = module = users, action = list, return = json
url.com/users/list.json?from=0&to=15 equal = module = users, action = list, return = json, from = 0, to = 15
Is this possible? I've been banging my head against a wall for a long time trying to get this work so I'm putting a bounty on it
You could try:
RewriteRule ([-A-Za-z0-9]+)/([-A-Za-z0-9]+)\.(json|xml)$ /testrewrite.php?module=$1&return=$3&action=$2 [L,QSA]
The QSA option will keep the query strings in tact.
The RewriteRule pattern simply does not match the requested URL path as the pattern for the third path segment [0-9]+ does not match List.
Apache's %{QUERY_STRING} will maintain the GET variables in your rules. For example:
RewriteRule ^([-A-Za-z0-9]+)/([-A-Za-z0-9]+).([-A-Za-z0-9]+)$ index.php?module=$1&action=$2&return=$3?%{QUERY_STRING}
I’m having trouble doing both of these at once with .htaccess.
Removing index.php is working, but trying to add the force lowercase keeps throwing a 500 error. I am using codeigniter. Any help is appreciated!
here’s my .htaccess code:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?$1
RewriteMap lc int:tolower
RewriteCond %{REQUEST_URI} [A-Z]
RewriteRule (.*) ${lc:$1} [R=301,L]
The php code suggested does not work if you are just trying to force to lowercase. Below is the correct php code.
$url = $_SERVER['REQUEST_URI'];
$pattern = '/([A-Z]+)/';
if(preg_match($pattern, $url)) {
$new_url = strtolower($url);
Header( 'HTTP/1.1 301 Moved Permanently' );
Header( 'Location: ' . $new_url );
exit;
}
// your code here
Discussion Found Here Force lowercase .htaccess
That is because it is impossible, let me explain.
Removing the index.php still sends all requests to index.php/yadda/yadda so the requested uri still has the index.php in it even though you do not see it or add it into the url.
The redirect (triggered by the 2nd rewrite rule) nulls the index section so you would then get mysite.com/index.php/lowercase/
BUT beyond all this RewriteMap can only be declared in your Httpd.conf file, you would declare it there with:
RewriteMap lc int:tolower
Then in your .htaccess file use your variable lc, but then again only one of the two will win you can't have both.
You will either get the URL lowercase or have the site working without using the index.php because they are always going to conflict because of the nature of what each one does.
Really the only way I can see it happening is in php, like so:
$this->load->helper('url');
$your_URL = uri_string();
preg_match_all('/[A-Z]/', $your_URL, $match) ;
$total_count = count($match [0]);
if($total_count > 0){
$new_line = strtolower($your_URL);
redirect($new_line);
}
This I would put into the main construct of your classes, I hope this helps you.
I want the following rules but I don't seem to get the right setup.
<domain>/training-courses/
both with or without the slash at the end it should go to:
<domain>/?index.php?page=training-courses
and for each variable extra after this I want it to behave like this:
<domain>/training-courses/success/another-value/and-yet-another/
to
<domain>/?index.php?page=training-courses&val1=success&val2=another-value&val3=and-yet-another-value
If it's not possible to have the option for unlimited leading variables, i'd like to have at least 2 variables after the page variable
Is this possible? and how do I get this sorted out?
I have this so far:
RewriteEngine On
RewriteRule ^test/([^/]*)/$ /test/index.php?pagina=$1&val1=$2
RewriteRule ^test/([^/]*)$ /test/index.php?pagina=$1&val1=$2
RewriteRule ^test/([^/]*)/([^/]*)/$ /test/index.php?pagina=$1&val1=$2
RewriteRule ^test/([^/]*)/([^/]*)$ /test/index.php?pagina=$1&val1=$2
RewriteRule ^test/([^/]*)/([^/]*)/([^/]*)/$ /test/index.php?pagina=$1&val1=$2&val2=$3
RewriteRule ^test/([^/]*)/([^/]*)/([^/]*)$ /test/index.php?pagina=$1&val1=$2&val2=$3
You're quite correct, you can't handle unlimited variables as sub-folders in the way you would like to, mod_rewrite just doesn't support it.
However, in answer to your first problem, to make the trailing / optional, change your rules to the following:
RewriteRule ^test/([^/]*)/?$ /test/index.php?pagina=$1
RewriteRule ^test/([^/]*)/([^/]*)/?$ /test/index.php?pagina=$1&val1=$2
RewriteRule ^test/([^/]*)/([^/]*)/([^/]*)/?$ /test/index.php?pagina=$1&val1=$2&val2=$3
After hours and hours of struggeling it just WON'T work. Since unlimited variables just isn't supported I'm ok with two variables besides the page (pagina). What I have now is this:
RewriteEngine On
RewriteRule ^(test/images|test/css|test/js|test/lib)($|/) - [L]
RewriteRule ^test/(.*)/(.*)/(.*)/ test/index.php?pagina=$1&e=$2&t=$3
RewriteRule ^test/(.*)/(.*)/(.*) test/index.php?pagina=$1&e=$2&t=$3
RewriteRule ^test/(.*)/(.*)/ test/index.php?pagina=$1&e=$2
RewriteRule ^test/(.*)/(.*) test/index.php?pagina=$1&e=$2
RewriteRule ^test/(.*)/ test/index.php?pagina=$1
RewriteRule ^test/(.*) test/index.php?pagina=$1
None of the RewriteRules work except from the first one which excludes folders from the other rewriterules. With working I mean it will actually redirect the URLs to index.php but I can't get the values in PHP through ie $_GET['pagina']
Strange thing is this WILL work, though is way too limited for my liking:
RewriteEngine On
RewriteRule ^(test/images|test/css|test/js|test/lib)($|/) - [L]
RewriteRule ^test/(.*)/ test/index.php?pagina=$1
I would like to come back to my own question and answer it. For a while now i'm using exactly what I want.
First off I have this in my htaccess:
<IfModule mod_rewrite.c>
RewriteEngine On
# existing folders or files
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.* - [L]
# non-existing folders or files
RewriteRule ^(.*)/? index.php?p=$1 [L]
</IfModule>
This allows to access real files at all times. If the path does not exist it will pass the entire path to index.php.
In index.php I have the following code at the top:
// Split the URL in all its components
$request = parse_url(strip_tags($_GET['p']));
// Only take the path without any leading slashes
$path = rtrim($request['path'], '/');
// Split each variable from eachother
$path_array = explode("/", $path);
if(count($path_array)){
// By default I select the first variable as the page I will include later on
$page = $path_array[0];
// Each other variable I will pass as $val[#nr] starting with 1. Just to be sure I'm going to strip tags and slashes
for($i=1;$i<count($path_array);$i++){
$path_array[$i] = strip_tags($path_array[$i]);
$path_array[$i] = stripslashes($path_array[$i]);
$val[$i] = $path_array[$i];
}
}
else{
// If $path_array doesn't contain multiple variables lets assume $path will contain the $page
$page = $path;
}
// If $page is empty let's take on the default page to include later on
if(empty($page)){
$page = "home";
}
if(file_exists($page . ".php")){
include($page . ".php");
}
else{
echo "Page " . $page . ".php does not exist.";
}
To give you some examples of the posibilities:
domain.com/ will include home.php
domain.com/product/ will include product.php
domain.com/product/298833/ will include product.php and parse 298833 as $val[1];
domain.com/product/298833/purple-candle will include product.php and parse 298833 as $val[1]; and purple-candle as $val[2]; Notice the leading slash not being included. It does not matter.
I'm open for improvement or tips in general. For now this is definitely the answer I was looking for back when I asked this question.
I have a url http://domain.com/module/controller/action/get1/value1/?get2=value2&get3=value3 I want to use Mod_Rewrite to change the ?&= to appropriate / slashes inline with the first GET variable.
I also need to avoid conflicts with my current Mod_Rewrite rules:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ zend.php [NC,L]
If you don't need the GET parameters in their native $_GET container, you could leave the htaccess file as is, and have the front controller (I assume you are using PHP) do the parsing and not mod_rewrite.
You would have to access the $_SERVER["REQUEST_URI"] and parse out the parameters before any other URL parsing (I think you are using the Zend Frameworks') kicks in.
This works only if you can modify the part of your program that needs value1 value2 value3 etc. If it's some Zend component that needs the parameters, and that component fetches them directly from $_GET, this will not work for you and you may in fact have to build mod_rewrite instructions.
Btw, you are aware by the way that with the method in your .htaccess, invalid links to images, CSS files and other media types will all be routed to zend.php?
Try putting these rules in front of yours:
RewriteCond %{QUERY_STRING} ^([^&=]+)=([^&]+)&(.+)
RewriteRule ^ %{REQUEST_URI}%1/%2/?%3 [N]
RewriteCond %{QUERY_STRING} ^([^&=]+)=([^&]+)$
RewriteRule ^ %{REQUEST_URI}%1/%2/? [L,R]
I could not find a nice way to do this... so I resolved to write some minimised PHP code at the top of my zend.php.
list($sURL, $sQuery) = explode('?', $_SERVER['REQUEST_URI']);
$sOriginalURL = $sURL;
if ('/' !== substr($sURL, -1)) $sURL .= '/';
if (isset($sQuery)) {
foreach (explode('&', $sQuery) as $sPair) {
if (empty($sPair)) continue;
list($sKey, $sValue) = explode('=', $sPair);
$sURL .= $sKey . '/' . $sValue . '/';
}
}
if (isset($sQuery) || $sOriginalURL !== $sURL) header(sprintf('Location: %s', $sURL));
If anyone can improve on this please comment below.