1

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?

Community
  • 1
  • 1
user1977072
  • 51
  • 1
  • 1
  • 6
  • Do you want to redirect this `http://atwd/books/course?course_id=CC100&format=XML&submit=Submit` to this `http://atwd/books/course/CC100/XML`, or is the other way around? ¿What are the other examples and descriptions for? – Felipe Alameda A Jan 14 '13 at 12:32
  • I don't suppose it's because in your rewrite condition you're calling it course_id and in the rewrite rule you're calling it course is it? – Rick Calder Jan 14 '13 at 13:26
  • @faa I don't need to redirect that URL. I just need to format the URI into segments instead of a query string, which it is now. – user1977072 Jan 14 '13 at 14:45
  • @Rick_Calder I think the 'course' text will just be outputted to the browser and the percentages represent the rewrite conditions. – user1977072 Jan 14 '13 at 14:48

3 Answers3

1

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>
Community
  • 1
  • 1
Jon Lin
  • 142,182
  • 29
  • 220
  • 220
  • Whoa, your comments make me understand! I think it'll be a couple of days until I figure out the answers, but the link you gave explaining "The notion of "converting URLs" is really helpful. You are good at explaining this! – user1977072 Jan 14 '13 at 17:14
  • Hi Jon, I read up on the 2 step rewrite process. My URL is now this `http://atwd/books/course/CC100/XML/?Submit` but I now can't access any of the `$_GET` variables, which I need to do. My code is `# check if the actual request if for "this1" RewriteCond %{QUERY_STRING} ^course_id=([^&]+)&format=([^&]+)&submit=([^&]+)$ # redirect to "this2" RewriteRule ^/?books/course$ /books/course/%1/%2/?%3 [R,L]` So do I need to redirect "this2" back to "this1"? If I do that, will I mess up the URL and convert it back to that query string I started with? – user1977072 Jan 16 '13 at 13:36
  • @user1977072 If you only do an external redirect, then what the server gets at the end is what was redirected, no $_GET parameters, because the new request doesn't have any. If you need to internally rewrite them back, then you need to do something completely different – Jon Lin Jan 16 '13 at 20:47
  • Thanks Jon, that's formatting my URL correctly. I don't know what you mean by "links", did you mean hyperlinks? I don't have any hyperlinks, I'm just using a form that has the action of `books/course/$course_id/$format`, but $course_id and $format (from `extract($_GET)`) are undefined, as though the internal redirect isn't working. – user1977072 Jan 17 '13 at 12:38
0

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";
Steve
  • 5,771
  • 4
  • 34
  • 49
0

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.

Wesley
  • 301
  • 1
  • 2
  • 8
  • I need to use a GET method. Sorry, there's no bigger picture of what I want to be doing, it's just what I'm told. – user1977072 Jan 15 '13 at 08:34