Ever wonder why you can’t use query strings with CodeIgniter? This post will explain to some degree, but more importantly, show you how to parse query strings and how to get the GET back in CodeIgniter!
I’ve been using CodeIgniter for a couple years now. It’s small, it’s simple, it’s powerful. Admittedly, it’s not perfect (what framework is?) but it’s a wonderful way to slap together a website using MVC design principles and PHP. I do have one big complaint, however.
The Hated $_GET global
The CodeIgniter developers have some strange obsession with killing all GET data. It appears, from the manual at least, that they strongly discourage you from using query strings. For example, the following manual entry states:
By default, URLs in CodeIgniter are designed to be search-engine and human friendly. Rather than using the standard “query string” approach to URLs that is synonymous with dynamic systems, CodeIgniter uses a segment-based approach:
You’ll notice that I have highlighted the words, “By default,…” because you can, in fact, turn on query strings in CodeIgniter, however there is an important trade-off to note (besides saying goodbye to those pretty URL’s:)
Please note: If you are using query strings you will have to build your own URLs, rather than utilizing the URL helpers (and other helpers that generate URLs, like some of the form helpers) as these are designed to work with segment based URLs.
Okay, admittedly, it’s not a big deal to build your own URL’s. I mean we used to do that all the time, right? However, what if you have used the “default method” of the segment-based approach and suddenly you need to pass GET values to your CodeIgniter application? Let’s also say that you’ve used many of those helpful URL functions, etc. Now, for the cost of enabling query strings, in the manner indicated by the manual, for that one page, you’ve got plenty of re-factoring to do! Not cool.
I know this sounds like a fantasy scenario, but it’s real. It happened to me. On two different occasions, working with two different payment gateway API’s, I suddenly had to provide postback URL’s. In both instances, the postback URL’s that were directed to my website, attached query-string variables to the URL in order to provide the relevant data (receipt number, etc.) Obviously, this is something I had no control over because I had to adhere to the API convention and they didn’t offer alternatives for “segment-based” Web frameworks! I realize that I could have used a standalone script to handle these requests, but that could be potentially confusing for future developers (including myself after a few months) because the standalone script would reside outside of the framework. Also, I have based the entire application on the framework. The framework keeps my code organized in a way. I don’t want to have to use scripts that do not adhere to my conventions. I want to use the framework for all my code! More importantly, what about my models, libraries, helpers, etc? The framework shouldn’t force you to make the decision not to use it. It should, at least, provide a way to use a long-establish standard without compromising one of the best benefits of the framework.
I can understand disabling the $_GET super global (and query-string usage) by default when the whole framework is geared towards segment-based URL’s. What I can’t understand is why they make it so hard to enable query strings for situations when you might actually need them. There is no simple configuration Boolean variable you can flip on and off!
So, why can’t we just specify a controller/method URI and tack on a query string? Admittedly, this gets a little complex to depend on with mod_rewrite and other factors outside of the control of the CodeIgniter developers. However, no attempt has been made to allow for the possibility. For an explanation, let’s go back to the manual:
The security filtering function is called automatically when a new controller is invoked. It does the following:
- Destroys the global GET array. Since CodeIgniter does not utilize GET strings, there is no reason to allow it.
- Destroys all global variables in the event register_globals is turned on.
Okay, clearly there is a reason to allow it! I think we can tally up the real reasons behind destroying query string data to a matter of programmer laziness! I know that sounds harsh, but the manual clearly states (to paraphrase,) “Let’s not bother with storing GET data anywhere in the CodeIgniter super object because we don’t use it anyway. Phew, don’t have to worry about that anymore!”
Let’s put it back! Methods for enabling $_GET in CodeIgniter
Luckily, there are a few ways we can use GET variables without having to give up the segment-based approach (and all those nice URL functions!)
Method 1: Extend The Input Class
If you want to enable codeigniter to get query string variables globally, you can do it with a few easy steps:
- Create a MY_Input class in application/libraries
- Update your application/config/config.php file: Change $config['uri_protocol'] to “PATH_INFO”
- If you are using mod_rewrite to hide index.php, make sure you have a slash in your rule after index.php: RewriteRule ^(.*)$ index.php/$1 [L]
/*
|--------------------------------------------------------------------------
| URI PROTOCOL
|--------------------------------------------------------------------------
|
| This item determines which server global should be used to retrieve the
| URI string. The default setting of "AUTO" works for most servers.
| If your links do not seem to work, try one of the other delicious flavors:
|
| 'AUTO' Default - auto detects
| 'PATH_INFO' Uses the PATH_INFO
| 'QUERY_STRING' Uses the QUERY_STRING
| 'REQUEST_URI' Uses the REQUEST_URI
| 'ORIG_PATH_INFO' Uses the ORIG_PATH_INFO
|
*/
$config['uri_protocol'] = "PATH_INFO";When using mod_rewrite
If you’re hiding index.php with mod_rewrite, make sure you use a slash after index.php. I could never make this work with PATH_INFO configured until I pulled out the question mark (?) in my RewriteRule.
RewriteRule ^(.*)$ index.php/$1 [L]Using the get method of the Input class
The nice part about this method is that you can refer to get variables using the input class. This has the advantage of easily utilizing the cross-site-scripting tools in the Input class (and keeping with the “CodeIgniter way” of doing things.)
Conclusion
I had to do some “tinkering” to get this method to work; but in the end, it’s a fairly simple hack that requires minimal changes.
Our next method requires no configuration changes nor extended libraries whatsoever.
Method 2: Use parse_str to Grab GET data out of REQUEST_URI
This method should, perhaps, be subtitled, “The Quick and Dirty Method” as it’s extremely easy to implement: one line of code.
Despite what the manual states, CodeIgniter fails to destroy all global variables. For example, $_SERVER['REQUEST_URI'] shows what was given from the browser as the URL path. (Example: /controller/method?foo=bar.)
Having this data, we can use PHP’s parse_str function to parse $_SERVER['REQUEST_URI'] and rebuild the $_GET array. We also have to utilize substr to strip away the /controller/method part. Otherwise, we’ll end up with a $_GET key similar to “/controller/method?foo” when we just want our associative array key to be “foo.” It’s important to note that we can still use the fabulous Input class to filter our query-string data (it’s just not quite as pretty) against cross-site-scripting attacks.
My preference because it’s a “genuine hack”
I should note that this is the method I used for my payment gateway postbacks. In my particular situation, this was the best fit because I needed query-string variables for a single URL in the entire site. I really didn’t want to have to extend CodeIgniter or change my Apache settings for one URL (I’m fine with segment-based URL’s as long as they’re in my control.) I just put this one line of code in my controller method where it was needed.
If you don’t want the bother of dropping this code into each one of your controller methods, you can easily incorporate this into a helper function and make a simple function call any time you need $_GET. If you want to enable rebuilding $_GET globally, you can also take advantage of setting this code up in a pre_controller hook.
The best part of this method is that it works with CodeIgniter out-of-the-box. No configuration changes or extended libraries should be necessary. Always a “plus” in my book.



You rock. I have been coding in PHP since 2002 and just recently started using CodeIgniter. Although, like you, I respect CI’s approach, having to do away with my beloved GET method irked me. For most things the URI segment approach would work great, but I wanted to put in forward slashes into the segment… instant fail. Your method (2nd one) worked beautifully.
thank you really!!
this is a pretty information
Thanks, a great help for me today.
I tried to use method #2 at Sidepon.com, but it went straight to error_404 page. The $config['uri_protocol'] = “PATH_INFO” doesn’t work on my webserver. What can i do?