In my CMS I store all pages in a database. If you request a page currently it works like this:
Requested URI: www.xyz.com/site.html
.htaccess: mod_rewrite creates: /index.php?q=site
index.php: Looks up in Database for the entry site.
To clean up the URLs I like to have URLS like this: www.xyt.com/about/site.html or www.xyt.com/about/groups/groups.html
In my Database is an entry for every Page called owner which represents the Parent Site.
The Problem for me is that the number of 'folders' is not fixed.
So i thought I should Change www.xyt.com/about/site.php to /index.php?q=about-site in the .htaccess and than write a PHP function which finds the site site with the Parent about
What would be the RewriteRule?
I that a good way or is there an other (better) way?
Changing the foo/bar/about/site/etc.html to index.php?q=foo-bar-about-site-etc is much more difficult with mod_rewrite than it is with PHP. Just do this in php, get the $_GET['q'] variable and explode the string into an array or something using the / flags. It's also better this way because you'll know for sure that the / characters are reserved and you won't end up having to resolve stuff like /foo-bar/about/site. The rules would look something like:
RewriteEngine On
RewriteCond %{THE_REQUEST} \ /+index\.php\?q=([^&\ ]+)
RewriteRule ^ /%1.html [L,R]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)\.html$ /index.php?q=$1 [L]
Related
Bounty Note: I've found my solution for my question using add_rewrite_rules. I will reward the bounty to anyone who can provide me with the same solution in apache RewriteRules format.
I've read How can I create friendly URLs with .htaccess? but it still difficult and complicate to me.
I am running WordPress Multisite, and I have a sub domain website cp.example.com and I'm writing a php app on this sub domain.
I have a website address that is looks like this:
http://cp.example.com/sales.php?id=12345&userid=123456&uid=83hkuhdqhuhd873xsuhdqwiuhdiq
Is it possible for me to let user access the website via:
http://cp.example.com/sales/12345/userid/123456/83hkuhdqhuhd873xsuhdqwiuhdiq
And if I were to do that will php still be able to do $_GET on the values?
e.g $_GET['id'], $_GET['userid'] and $_GET['uid']?
I'm using WordPress for my base, but i'm writing the app end, using a different table.
I'm trying to avoid using custom post type just to achieve the above.
I've tried the following.
Create a template file view_sales.php in view_sales.php I will require $_GET['id'], $_GET['userid'] and $_GET['uid'] in order to retrieve info from mysql.
in view_sales.php I've also used a different header file and have get_header('sales');
in header-sales.php I've added the following code gotten from the above stack overflow page.
$path_components = explode('/', $_GET['url']);
$id=$path_components[0];
$userid=$path_components[1];
$uid=$path_components[2];
I created a new wp page with slug sales so now the website is
http://cp.example.com/sales/?id=123456&userid=123456&token=98917397219372iheu1i
I only have one .htacess website in my /public_html/example.com domain since it's a multisite so I added the code suggested above to my .htaccess and now it looks like this.
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
</IfModule>
Nothing is working at the moment, still redirecting to the ugly url.
Edited:
I've tried the following
RewriteCond %{HTTP_HOST} !^cp\.example\.com [NC]
RewriteRule ^listing/([a-z0-9]+)$ listing/?action=$1 [L,NC]
RewriteRule ^view/([a-z9-9]+)$ view/?id=$ [L,NC]
I tried different variants of all the above but nothing works.
Edited for add_rewrite_rule method which i tried
function pa_custom_rules() {
add_rewrite_rule('^/listing/([^/]+)/$', 'index.php?pagename=listing&action=$matches[1]', 'top');
}
add_action('init', 'pa_custom_rules');
Printed the rewrite array and I can see the new rule
[^/listing/([^/]+)/$] => index.php?pagename=listing&action=$matches[1]
Visiting index.php works but going to /listing/test/ fails. It returns 404 error.
Finally solved problem which bothered me for last few days.
It appears Rewrite rules for specific domains does not work.
If you wish to change
http://subdomain.example.com/listing?action=add(e.g. or DEL or VIEW)
of a Wordpress MULTISITE to
http://subdomain.example.com/add/ (e.g.or DEL or VIEW)
you have to not only add rewrite rules, but it's also compulsory to rewrite/add the tag to query_var.
You need to add the following to function or create a plugin to initiate it once.
function pa_custom_rules() {
add_rewrite_rule('listing/(.*)$', 'index.php?pagename=listing&action=$matches[1]', 'top');
add_rewrite_tag('%action%', '(.*)');
}
add_action('init', 'pa_custom_rules');
once done you will be able to access http://subdomain.example.com/listing/add
In your page (in this case, my page name is 'listing'), you will no longer get 404 error and you can get the value of "action" (in this case Add/Del/View) by using
http://subdomain.example.com/listing/**add**
$a = get_query_var('action');
echo $a; //prints **add**
Note: You cannot get the value of action using $_GET like how RewriteRule works, but this should be able to get most things done.
I can keep working on wordpress and get all my customise beautiful links and throw away my last 3 days of work exploring Laravel and Symfony3. Thank God.
I have a website that is like this
http://cp.example.com/sales.php?id=12345&userid=123456&uid=83hkuhdqhuhd873xsuhdqwiuhdiq
Is it possible for me to let user access the website via
http://cp.example.com/sales/12345/userid/123456/83hkuhdqhuhd873xsuhdqwiuhdiq
Yes, its possible, e.g.:
RewriteEngine On
RewriteRule ^sales/(\d+)/userid/(\d+)/([a-z0-8]+)$ sales.php?id=$1&userid=$2&uid=$3 [L,NC]
And if i were to do that.. will php still be able to do $_GET on the
values?
e.g $_GET['id'], $_GET['userid'] and $_GET['uid']
Yes, of course php will be able do that.
OK, first of let me just say I understand that this is a question that has been asked before. I just can't narrow it down to keywords and find what I'm looking for. So sorry in advance if this is a duplicate. htaccess rewrite is like black magic to me... I can't really get it to work.
To the question at hand:
I'm writing a simple barebone php/html site. I haven't done this in about 10 years (I usually use some CMS (wordpress, joomla etc.)). I'm trying to get a handle on some of the things that "come for free" with these CMSs. Like pretty URLs.
I have a simple index.php with some includes to build the pages. Then I have my includes folder with my dynamic content.
So two case examples of the actual URLs
index.php?page=index (my main page)
index.php?page=anotherpage (another page)
But what if I want to go to
index.php?page=a-sub-page-to-another-page
This is my PHP (index.php in web root folder)
if(isset($_GET["page"])){
$page = $_GET["page"];
$filename = "/includes/" . $page . ".php";
if(file_exists($filename)){
include("/includes/head.php");
include("/includes/navbar.php");
include $filename;
include("/includes/footer.php");
}else{
include("/includes/404.php");
}
}else{
include("/includes/head.php");
include("/includes/navbar.php");
include("/includes/index.php");
include("/includes/footer.php");
}
This is my .htaccess
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9_-]+)$ index.php?page=$1
This works as long as I don't have any sub pages. But If I try to go to [root]/somepage/somsubpage then it doesn't work anymore. Can someone please help me out here? I'm looking to replicate the effect I get with standard CMSs like wordpress, where all URLs are SEO friendly.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?page=$1
no in you php variable $_GET['page'] will have full url for example:
example.com/foo/barr
so $_GET['page'] => /foo/barr
However this is the first part only you would need do special function to map url to your page.
do SEO pages is to store do something like: example.com/some-url/of-my-special/page-in-here.1111.html so this is your url you make it as so you need to look at .xxxxx.html xxxx is variable so now if u write htaccess like:
RewriteRule ^(.*)\.(\d+)\.html$ index.php?fullurl=$1&pageid=$2
$_GET['fullurl'] => /some-url/of-my-special/page-in-here.1111.html
$_GET['pageid'] => 1111
Please! If anyone reads this... I'm still stuck on what to do... And I
can't find anything but mysql related articles. I've searched for
days. I just need to understand how to rewrite the PHP in my original
post to work with sub-pages, dynamically with variables. Ex.
index.php?page=index, index.php?page=secondPage,
index.php?page=secondPage&SubPage <-- this is the part I can't find
anything on. How do I get the php to look for more than one level
strings?
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ index.php?level1=$1
RewriteRule ^([^/]+)\/([^/])+$ index.php?level1=$1&level2=$2
RewriteRule ^([^/]+)\/([^/])+\/([^/])+$ index.php?level1=$1&level2=$2&level3=$3
I've done the due diligence, spending hours poring through searches and stack QA. No dice. So I finally come here to request help.
Apache HTTP Server
PHP 5.3
I have dirty urls:
.cc/store/index.php?route=checkout/cart
.cc/store/index.php?route=common/home
.cc/store/index.php?route=product/product&product_id=111
I'd like to clean them so when a user clicks on a dirty link or types a dirty url they get a clean url in the address bar:
.cc/store/cart
.cc/store/home
.cc/store/product/11
Currently I have my htaccess file in:
.cc/store/.htaccess
I know I need in htaccess:
RewriteEngine On
But is this the right path?:
RewriteRule !/index.php?route=(A-Z)/(A-Z)&(*)$ /$2/$3
Q1: Do I need to just edit the htaccess file or will I also have to write some php?
Q2: What htaccess / php code do I write to get the desired clean urls? I want to see clean urls in the address bar of my browser.
Thanks in advance.
Whatever is generating those URLs, be it PHP or simple HTML, will need to be updated to contain the new URLs. mod_rewrite simply takes the "Clean" url and translates it into the original "dirty" one so your original code can still function, with the same parameters.
This:
RewriteRule !/index.php?route=(A-Z)/(A-Z)&(*)$ /$2/$3
Isn't what you want. You're going to need 2 types of rules, ones that externally redirect the browser to the URL that you want to see, then ones that internally rewrite to the URL that your system can understand (the "dirty" ones). So something like:
RewriteEngine On
RewriteBase /store/
RewriteCond %{THE_REQUEST} \ /+store/index\.php\?route=checkout/cart
RewriteRule ^ /store/cart? [L,R]
RewriteCond %{THE_REQUEST} \ /+store/index\.php\?route=common/home
RewriteRule ^ /store/home? [L,R]
RewriteCond %{THE_REQUEST} \ /+store/index\.php\?route=product/product&product_id=([^&\ ]+)
RewriteRule ^ /store/product/%1? [L,R]
RewriteRule ^cart$ index.php?route=checkout/cart [L,QSA]
RewriteRule ^home$ index.php?route=common/home [L,QSA]
RewriteRule ^product/(.+)$ index.php?route=product/product&product_id=$1 [L,QSA]
You can't make it "wildcard" like matching because you're changing something like "X/Y" to just "Y", which means when you internally rewrite it back, the "X" part is lost forever.
I'm trying to convert a query string;
http://atwd/books/course?course_id=CC100&format=XML&submit=Submit
Into a segment URI;
http://atwd/books/course/CC100/XML
I'm working in CodeIgniter.
I was looking at a stackoverflow answer that said to check CodeIgniter's URL segment guide, but I don't think there's any information on how to convert a query string into a segment URI. There is, however a way to convert a segment URI into a query string, which is bringing up a load of results from Google too.
Following another stackoverflow answer, I tried this in my .htaccess file but nothing seemed to work
RewriteCond %{QUERY_STRING} ^course_id\=([^&]+)\&format\=([^&]+)$
RewriteRule ^$ /course/%1/format/%2 [R,L]
In my entire .htaccess file I have this;
<IfModule mod_rewrite.c>
RewriteEngine on
#Source: http://codeigniter.com/user_guide/general/urls.html
#Removal of index.php
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /index.php?route/$1 [L]
#Source: https://stackoverflow.com/questions/3420204/htaccess-get-url-to-uri-segments
#Format Course function requests
RewriteBase /
RewriteCond %{QUERY_STRING} ^course_id\=([^&]+)\&format\=([^&]+)$
RewriteRule ^$ /course/%1/format/%2 [R,L]
</IfModule>
This is in my root directory of Codeigniter screenshot
My code in the .htaccess file isn't working, I refresh the page and nothing happens. The code to hide the index.php is working though. Does anyone know why?
The notion of "converting URLs" from one thing to another is completely ambiguous, see the top part of this answer for an explanation of what happens to URLs when redirecting or rewriting: https://stackoverflow.com/a/11711948/851273
There's 2 things that happen, and I'm going to take a wild stab and guess that you want the 2nd thing, since you're complaining that refreshing the page doesn't do anything.
When you type http://atwd/books/course?course_id=CC100&format=XML&submit=Submit into your browser, this is the request URI that gets sent through mod_rewrite: /books/course. In your rule, you are matching against a blank URI: RewriteRule ^$ /course/%1/format/%2 [R,L]. That's the first reason your rule doesn't work. The second reason why it doesn't work is because above that, everything except images and index.php and robots.txt is being routed through index.php. So even if you were matching against the right URI, it gets routed before your rule even gets to do anything.
You need to correct the pattern in your rule to match the URI that you expect to redirect, and you need to place this rule before the routing rule that you have. So everything should look roughly like this:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{QUERY_STRING} ^course_id\=([^&]+)\&format\=([^&]+)$
RewriteRule ^/?books/course$ /course/%1/format/%2 [R,L]
#Source: http://codeigniter.com/user_guide/general/urls.html
#Removal of index.php
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /index.php?route/$1 [L]
</IfModule>
You'll need to tweak the paths to make sure they match what you are actually looking for.
To both redirect the browser and internally rewrite back to your original URL, you need to do something different.
First, you need to make sure all of your links look like this: /course/CC100/format/XML. Change your CMS or static HTML so all the links show up that way.
Then, you need to change the rules around (all before your codeigniter routing rule) to be something liek this:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
# redirect browser to a URI without the query string
RewriteCond %{THE_REQUEST} ^(GET|HEAD)\ /books/course/?\?course_id=([^&]+)&format=([^&]+)
RewriteRule ^/?books/course$ /course/%2/format/%3? [R,L]
# internally rewrite query string-less request back to one with query strings
RewriteRule ^/?course/([^/]+)/format/([^/]+)$ /books/course?course_id=$1&format=$2&submit=Submit [L]
#Source: http://codeigniter.com/user_guide/general/urls.html
#Removal of index.php
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /index.php?route/$1 [L]
</IfModule>
I'm not going to address the misunderstanding already addressed pretty well in the other answer and comments, and I can't speak for CodeIgniter specifically, but having given their URL routing docs a quick skim, it seems pretty similar to most web frameworks:
You probably just want to direct all traffic (that doesn't match physical files) to the frontend web controller (index.php) and handle the URL management in CodeIgniter's routing, not a htaccess file.
To do that, your htaccess could be as simple as:
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.php [QSA,L]
</IfModule>
This, as I said, will redirect any traffic that doesn't match an physical file such as robots.txt or an image to your index.php.
Then, using the routing as described in the docs (http://ellislab.com/codeigniter/user-guide/general/routing.html) you can take in parameters and pass them to your controllers as you see fit, there is no need to 'convert' or 'map' anything, your URL's don't need to resolve to /?yada=yada internally, based on your routing rules CodeIgniter can work it out.
You'll need wildcard routes such as this from the docs:
$route['product/:id'] = "catalog/product_lookup";
A rough example of what yours might end up looking like would be something like:
$route['course/:id/format/:format'] = "course/something_or_other_action";
If I'm understanding you correctly, you might be over-thinking it. I have something similar in my own code.
I have a controller named Source. In that controller, I have the following method:
public function edit($source_id, $year)
{
# Code relevant to this method here
}
This produces: http://localhost/source/edit/12/2013, where 12 refers to $source_id and 2013 refers to $year. Each parameter that you add is automatically translated into its own URI segment. It required no .htaccess trickery or custom routes either.
I am about to attempt writing of a photo sharing script and a script/rewrite that transforms numbers into descriptive names. I have a vague idea on how to go about doing this, so I was looking for some general comments/guidance.
Issue 1: I need to have a URL source for a photo which is stored above my root directory. I plan on appending the photo name (which is stored in my database) to my url as a query string, such as: www.mywebsite.com/getphoto.php?12_3.jpg and then writing a php script (getphoto.php) which takes the portion after the '?' and gets that photo from above the root.
Does this make sense and would there be any things to consider?
Issue 2: I want to transform a number at the end of my URL to a descriptive name (ie typing in facebook.com/4 displays facebook.com/zuck). I am not really sure the best way to go about doing this and was hoping for some guidance to get going in the right direction.
Thanks!
For Issue 1: a simple rewrite can handle that, you need to use the [QSA] flag. Something like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^.*\.(jpeg|jpg|gif|png|bmp)$
RewriteRule ^(.+)$ /getphoto.php?photo=$1 [L,QSA]
This will rewrite behind the scenes the url http://mywebsite.com/12_3.jpg to http://mywebsite.com/getphoto.php?photo=12_3.jpg Note that the 3rd rewrite condition wants the URI to end with an image extension, you may not need it.
For Issue 2, it depends on how something like "4" maps to "zuck". If you are going to hardcode them into your apache config, you can use a RewriteCond:
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/4$
RewriteRule ^.*$ /zuck [L]
RewriteCond %{REQUEST_URI} ^/5$
RewriteRule ^.*$ /mark [L]
etc. (or replace [L] with [R,L] to redirect instead of rewrite, or alternatively just use Redirect)
Redirect /4 /zuck
Redirect /5 /mark
etc.
If the mapping is stored in a database, your going to need to do this dynamically, perhaps as a php script to do a redirect, utilizing something similar to Issue 1. The rewrite rule would rewrite to something like /redirect.php?id=$1 and your redirect.php script would take the id and do a database lookup to see where to redirect the browser.