Register to post in forums, or Log in to your existing account
 

Post new topic  Reply to topic     Home » Forums » Zugg's Blog
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23377
Location: Colorado, USA

PostPosted: Sat Nov 01, 2008 2:51 am   

Debugging CodeIgniter using PhpEd
 
As I've mentioned in my other blogs (Life as a web developer and Choosing a PHP IDE), I've fallen in love with the CodeIgniter framework for PHP. However, getting a local debugger to work with it has been a challenge.

I have only found one PHP IDE that I could get to work properly, and it required a couple of changes to the base CodeIgniter libraries, along with some detailed setup of the server and the IDE. Much of the information on this subject on the net is out-dated and applies to older versions of CodeIgniter. So, in the interests of helping other PHP developers use this great framework, I'm going to give a step-by-step tutorial on how to start debugging with CodeIgniter and the PhpEd IDE.

CodeIgniter changes
One of the nice features of CodeIgniter is how it handles the URL for your web application. Your URL is always of the format: http://host/controller/function, where "controller" is the name of the controller (in the MVC model-view-controller paradigm), and "function" is the name of the function within the controller that you want to call. If you want to pass additional arguments to the function, like an "id" field, then you just add another segment to the URL. For example:

http://hostname/user/edit/123

would call the "edit" function of the "user" controller and pass "123" as the first argument of the function. No query strings. Just nice search-engine friendly URLs.

This nice feature has a major drawback, especially when dealing with debuggers: It can't handle query strings. Debuggers usually add various query string arguments to a URL to control the debugger. For example, the PHP Debugger (DBG) creates a URL like this:

http://hostname/index.php?DBGSESSID=1234567890

To handle a URL like this, some changes need to be made to the CodeIgniter core library files. The downside of these changes are that you'll need to make them every time you upgrade CodeIgniter. The advantage is that these changes will make it much easier to handle query strings in your applications so that you can have the best of both worlds: nice URLs with the option of additional optional query arguments.

The files we are going to modify slightly are the URI.php and Router.php files. Both are located in your system/libraries subfolder of CodeIgniter.

IMPORTANT NOTE about changes
All of these changes are for the 1.6.3 version of CodeIgniter (it has also been tested in v1.7). But any v1.5 or later should be able to handle these same changes. The exact line numbers of the changes might be different in your installation.

These changes have not been tested with different start pages (changing index.php to something else), or if you run CodeIgniter in a subdirectory. I'll eventually test those cases and update this procedure based upon what I find.

Finally, when running your CodeIgniter application on your local server, you may also need to change your 'base_url' config variable (in system\application\config.php) to 'http://localhost/' instead of whatever you might have on your specific server.

URI.php changes
Find the routine _fetch_uri_string (line 60). This routine is responsible for fetching the path part of the URL. First, let's add handling of the REQUEST_URI variable for those versions of PHP that have it, even with the "uri_protocol" is set to "auto" (normally CI doesn't look for this unless you set uri_protocol to "request_uri" which is mainly for PHP 5). We want to do this *before* we look for a query string. The highlighted code is what you want to add (line 73):


         $path = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : @getenv('PATH_INFO');         
         if (trim($path, '/') != '' AND $path != "/".SELF)
         {
            $this->uri_string = $path;
            return;
         }
         // No PATH_INFO?... What about REQUEST_URI?
         $path =  (isset($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : @getenv('REQUEST_URI');   
         if (trim($path, '/') != '')
         {
            $this->uri_string = $this->_parse_request_uri();
            return;
         }

         // No PATH_INFO?... What about QUERY_STRING?
         $path =  (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');   

This change will help CI grab the correct path information when query strings are added to a path. It might not work with old versions of PHP, but works fine with PHP 4.4.6+.

The more important change is to move the processing of the GET request down to the bottom of this routine. So in the same _fetch_uri_string routine, move the section of code that looks like:
Code:
         // If the URL has a question mark then it's simplest to just
         // build the URI string from the zero index of the $_GET array.
         // This avoids having to deal with $_SERVER variables, which
         // can be unreliable in some environments
         if (is_array($_GET) AND count($_GET) == 1 AND trim(key($_GET), '/') != '')
         {
            $this->uri_string = key($_GET);
            return;
         }

down so that it is just before the
Code:
         // We've exhausted all our options...
         $this->uri_string = '';

lines. This ensures that we are able to process the path information in the URL, even when query strings are given.

Router.php changes
Find the _set_routing() routine. This routine is responsible for processing the "uri_string" returned by the previous function. We need to change this to allow query strings. First we will strip any query string from the URI, and second we will check for the base "index.php" file and remove this if we have a default controller set in the CI config.php file. So, after the call to "$this->uri->_fetch_uri_string()", add the code that is highlighted below (line 93):

      // Fetch the complete URI string
      $this->uri->_fetch_uri_string();
      if (strpos( $this->uri->uri_string, '?')) {
         // strip query string
         $this->uri->uri_string = preg_replace( '/^(.*)\?.*$/', '\1', $this->uri->uri_string);
         }
      if ((strtolower( trim( $this->uri->uri_string, '/')) == 'index.php') && ($this->default_controller !== FALSE)) {
         // use the default controller if our path is just index.php
         $this->uri->uri_string = '';
      }

      // Is there a URI string? If not, the default controller specified in the "routes" file will be shown.
      if ($this->uri->uri_string == '')


config.php changes
You also have to make one small change to the config.php file in your system/application/config directory. File the configuration setting for "permitted_uri_chars". Now set it to this:
Code:
$config['permitted_uri_chars'] = '';

Yeah, I know, there is a big warning above this that says "do not change this unless you fully understand the repercussions" and "leave blank to allow all characters -- but only if you are insane.".

OK, *after* you get debugging working, you can come back here and tweak this a bit more. For example, I changed it to:
Code:
$config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-\?&=;,';

and it worked fine. The idea here is that you just want to add the extra characters needed to allow normal query strings. To handle the "?DBGSESSID=1234567;d=1..." query string, we need to add the ?&=; characters to the allowed list.

Other optional changes
If you want to make CodeIgniter more useful, you can also add a routine to the CI->input library to allow you to fetch "get" variables, just as easily as you fetch the normal "post" variables.

For those additional optional changes, I'll refer you to How to create mix urls (Segment + Querystring) article in the CodeIgniter forums. It's for an older version of CodeIgniter, but you'll see the similar changes to what I've mentioned above, and you'll see additional code for adding the "get" routine to the CI->input class.

I have found that the combination of these changes not only makes it easier to get debuggers working with CodeIgniter, but also help in my own applications. For example, even though I love the normal CI URLs, there are some cases where you still need query strings, such as when calling external sites like PayPal for ecommerce. Yes, you can modify your "htaccess" file to handle these exceptions in most cases. But sometimes it's just easier to allow the query string and use $this->input->get to retrieve the optional argument. Gives you a bit more flexibility in your application design.

Setting up a local web debugging server
Once you have CodeIgniter ready to go, the next thing you need is a local debugging environment, and that starts with a web server. If you already have a web server and PHP installed locally, skip to the next section. Otherwise keep reading.

I chose the XAMPP server package for Windows. Like other "amp" packages, this stands for "Apache, MySQL, and PHP". XAMPP also adds Perl (the second P). What I like about this package is that it comes with everything preconfigured, and includes *both* PHP4 and PHP5 with a simple batch file for switching back and forth between them. This makes it easier to test your application on both versions before deploying to a real site.

Just download the latest version and follow their instructions to install it. It was mostly painless, even on my Vista system, but here are a few rough edges:
  • Make sure you tell it to install Apache and MySQL as services.
  • You'll need to ignore the "control panel" icon that it puts in your system tray. To start/stop Apache you must use the Windows Services control panel on Vista and not their own XAMPP icon. I also had trouble using their own MySQL start/stop buttons, so again, I just used the normal Windows Services control panel. No big deal with this.
  • XAMPP comes set up for PHP5 by default. You need to run their /xampp/php-switch.bat file to switch to PHP4 if you want to use that by default (which I did).
  • The version of XAMPP that I installed did *not* install the correct MySQL library files for PHP4. MySQL changed their authentication method in v4.x, and the files for PHP4 are older than that. So if you want both PHP4 and PHP5 to use the proper authentication for MySQL 5.x (and you do), then find the MySQL 5.x DLL files for PHP4. I found them at PHP4+MySql blog site, but you can also just Google search "PHP4 MySQL DLL Windows". The php4ts.dll and libmysql.dll files should be placed within your /xampp/php/php4 directory, along with your /xampp/apache/bin directory if you have already switched XAMPP to PHP4.

That should be it. You should be able to point your web browser at http://localhost/ and see the XAMPP page. Follow the instructions there to finish setting up the security on your system. Their documentation is pretty good, and since the server is Apache, there is a lot of info on the net on setting up the httpd.conf file to put your web source files wherever you want them. In my case I just put my files within the /xampp/htdocs directory as per their default setup.

Installing the Debugger
To set up the PHP debugger on your server, the NuSphere PhpEd guys have created a nice little PHP script to help you. Download their dbg-wizard.php file and place it within your /xampp/htdocs directory and then point your web browser at http://localhost/dbg_wizard.php. It will analyze your version of PHP and Apache and will give instructions for which debugger library to download and what changes you need to make to your PHP.INI file.

In my case, I am running PHP 4 on a X86 Windows machine, so I needed to download their dbg-php-4.4.dll file and place it into my /xampp/php/extensions directory. Then, in my PHP.INI file (in both /xampp/apache/bin and /xampp/php/php4) I added the following lines:
Code:
zend_extension_ts=C:\xampp\php\extensions\dbg-php-4.4.dll
[debugger]
debugger.hosts_allow= localhost
debugger.hosts_deny=ALL
debugger.ports=7869

These lines must be added *before* the [Zend] section at the bottom of the file. Then, restart the Apache server on your system.

Setting up PhpEd
The final step was to set up the PhpEd IDE from NuSphere to use this debugger setup. Go to the Project/Project Properties menu and down in the Mapping section, set the "Run mode" to "HTTP mode (3rd party WEB server)" and then enter "http://localhost/" as the Root URL. In the Remote root directory, I entered "c:\xampp\htdocs".

The final important step is to enter the path to your main CodeIgniter file down in the "Default file to run" in your Project Properties. In my case, it was set to "c:\xampp\htdocs\index.php". But if you have put your CodeIgniter files in a different subfolder, than change this as needed for your system. This is the file that CodeIgniter will run when you tell it to debug your application.

So now, with all of this set up, you just set a breakpoint in your PHP code, and click the "Run with debugging" arrow (the green arrow with the D on it). It will stop on the first line of your code (you can turn this off in the PhpEd settings), so just click the Run with Debugging arrow a second time and it will run until it gets to your breakpoint. Then you can step through your code, examine variables, etc.

For another helpful reference on this topic, see Using XDebug with CodeIgniter in the CodeIgniter forums. It talks about the Zend debugger and is also for an older version of CodeIgniter, but it might give you additional information.

Conclusion
I hope this tutorial helps other people get PHP Debugging working with their CodeIgniter applications. It's a great framework, and PhpEd is a nice IDE to use with it.

If you find any errors or problems in this tutorial, please let me know by either posting a comment or sending me an email. Feel free to post this tutorial anywhere else as long as you retain a link to this site and my name (Mike Potter/Zugg) and email address (zugg@zuggsoft.com) for credit. I have included the links to the other authors who I give credit to for putting me on the right track to getting this all working. Please retain those links if possible, especially since they contain information for older versions of CodeIgniter that other people might still be using.

Keep in mind that while this worked great for me, every system can be a little different. As CodeIgniter, XAMPP, PhpEd, and the other software is updated, this procedure might change. Obviously there is no warranty or guarantee implied in this tutorial. You must take all responsibility for any changes made to your system. I'm not responsible for anything bad that might happen to your web site, computer, or your sanity when trying to get this all to work.

I hope this helped some people. Happy PHP coding!
Reply with quote
teaguer
Newbie


Joined: 10 Mar 2009
Posts: 1

PostPosted: Tue Mar 10, 2009 8:36 pm   
 
I signed up for your forum to specifically say thank you for posting this fix. I have been programming for over 15 years, but am new to php. Your fix helped a lot and i wanted you to know that someone is reading it and found it extremely useful.
Reply with quote
Fang Xianfu
GURU


Joined: 26 Jan 2004
Posts: 5155
Location: United Kingdom

PostPosted: Tue Mar 10, 2009 10:44 pm   
 
Guess this site's stellar google ranking is good for something! ;D
_________________
Rorso's syntax colouriser.

- Happy bunny is happy! (1/25)
Reply with quote
Cody
Newbie


Joined: 02 May 2009
Posts: 1

PostPosted: Sat May 02, 2009 5:47 am   
 
This is not working for me :-/.

I'm using CI 1.7.1 (latest version) and when I complete the "CodeIgniter changes" section and goto the url http://localhost/test/ it pulls up a CI generated 404 error. Which is actually not a real 404 error since it doesn't show in the apache logs.
I've installed CI into d:\xampp\htdocs\test\.
I can however get to the default welcome page if I do http://localhost/test/index.php/welcome/ which is kind of weird. But just doing http://localhost/test or http://localhost/test/index.php does not work. I've gone through this section twice and followed every direction.

Any help would be hugely appreciated!
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23377
Location: Colorado, USA

PostPosted: Mon May 04, 2009 6:48 pm   
 
As I mentioned above:
Quote:
These changes have not been tested with different start pages (changing index.php to something else), or if you run CodeIgniter in a subdirectory.

You are running CodeIgniter in a subdirectory (test) so you will need to make additional coding tweaks to your system.
Reply with quote
shinkenshin
Newbie


Joined: 05 Jul 2009
Posts: 3

PostPosted: Sun Jul 05, 2009 12:04 pm   
 
Hi Cody,
did you found the solution of the problem?

Where I can do some try I am not allowed to put CI in the server root.
I am newbie with CodeIgniter and I am learning.
So I am not able to tweak the example to solve this problem. Embarassed

This is my workspace:

Server root
|--MyCI_Application
|--|--system (CI Framework folder)
|--|--index.php

I think that would be a great thing to update this excellent tutorial.

Please, Zugg can you give me a little help?

Thank's in advance.
Kenshin
Reply with quote
shinkenshin
Newbie


Joined: 05 Jul 2009
Posts: 3

PostPosted: Tue Jul 07, 2009 2:30 pm   
 
...no one here???
Reply with quote
Fang Xianfu
GURU


Joined: 26 Jan 2004
Posts: 5155
Location: United Kingdom

PostPosted: Tue Jul 07, 2009 4:11 pm   
 
As useful as this post might be, this isn't a web development forum, so most of us don't really know what's going on in the OP. Zugg's only one guy and he's pretty busy with CMUD and might not have time to get back into this.
_________________
Rorso's syntax colouriser.

- Happy bunny is happy! (1/25)
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23377
Location: Colorado, USA

PostPosted: Tue Jul 07, 2009 4:22 pm   
 
Yeah, I said in my original tutorial that it would need modifications if you had Code Igniter installed in a sub-directory. I just haven't had the time to set up a test web site in a subdirectory and debug this myself, so people are pretty much on their own for that. You might want to post questions to the main Code Igniter Forums where you can get help from other Code Igniter users. All I can say is that setting up a debugger with Code Igniter is not for the novice programmer. Hopefully my examples will lead people in the right direction, but it's not intended to be a plug-play solution that works for everyone.
Reply with quote
shinkenshin
Newbie


Joined: 05 Jul 2009
Posts: 3

PostPosted: Tue Jul 07, 2009 5:47 pm   
 
Hi,

many thank's for the reply.

I am a professional software developer and I am working with PHP for about 6 years.
Now I am learning CI and for an urgent work I need to learn quickly... so I think that use the PhpEd debugger for me is very important.

Your article is very interesting and it works very well, but now I am too newbie for follow the right direction and fix further CI to use the PhpEd debugger in a subdirectory.

I think that someone else has had the need to install the framework in a subdirectory, it would be very useful if the "solution" will be shared. Smile

Kenshin
Reply with quote
rjarvis
Newbie


Joined: 01 Oct 2009
Posts: 2

PostPosted: Fri Oct 02, 2009 12:20 am   
 
Hi,

On the subdirectory issue, I found that the change needed is in the additional code in Router.php because the comparison

if (strtolower( trim( $this->uri->uri_string, '/') =='index.php' && ...

on the 5th extra line fails because the strtolower function returns 'my_subdir/index.php' when you ask for the default controller instead of just 'index.php'.

So all you need to do is to add some code which gets my_subdir from somewhere and prepends it (with a '/') to 'index.php' in that comparison.

The code I used for that (and I apologise in advance for its extreme clunkiness - I have no interest in 'golfing' it) is to put the following three lines in front
if the aforementioned comparison:

$rev_base_url = array_reverse(explode('/',trim($this->config->item('base_url'),'/')));
$end_base_url = $rev_base_url[0];
$uri_prefix = (strpos($end_base_url, '.') || $end_base_url == 'localhost') ? '' : $end_base_url.'/';

Line 1 turns the base_url from the config into an array and reverses it. Line 2 picks the last segment of the base_url by taking the first element of the reversed array. Line 3 then creates a uri_prefix using the last_segment and a '/' <b>only if</b> the last segment does not contain a '.' (so is not a domain name) and is not localhost (for your development environment). Undoubtedly this code is not bulletproof, but it works for me, and should also still work
even without a subirectory. If this solution doesn't work for you, then play around with an echo of strtolower( trim( $this->uri->uri_string, '/')
to see what changes you will have to make. I think it will be in the same place though.

In my case, the above comparison now becomes

if ((strtolower( trim( $this->uri->uri_string, '/')) == $uri_prefix.'index.php') && ($this->default_controller !== FALSE)) {

Thank you very much for the original solution, by the way. I would never have found it and it only needed a little tweak in the end to make it work for
my particular subdirectory setup.

I hope my "extra" solution works for others.

Richard
UPDATE: See modification to this solution in my post below - it covers a (very common) case I hadn't spotted before


Last edited by rjarvis on Sat Oct 03, 2009 10:40 am; edited 1 time in total
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23377
Location: Colorado, USA

PostPosted: Fri Oct 02, 2009 4:05 pm   
 
Richard: Thanks very much for posting this! I'm sure it will be really helpful for other CodeIgniter users!
Reply with quote
rjarvis
Newbie


Joined: 01 Oct 2009
Posts: 2

PostPosted: Sat Oct 03, 2009 10:37 am   
 
Small bugfix: the version I showed didn't work if index.php was missing from the uri! Instead the total fix is to replace

Code:
 
if ((strtolower( trim( $this->uri->uri_string, '/')) == 'index.php') && ($this->default_controller !== FALSE)) {
    // use the default controller if our path is just index.php
    $this->uri->uri_string = '';
 }


in the originally proposed modifications to Router.php with

Code:

$rev_base_url = array_reverse(explode('/',trim($this->config->item('base_url'),'/')));
$end_base_url = $rev_base_url[0];
$uri_prefix = (strpos($end_base_url, '.') || $end_base_url == 'localhost') ? '' : $end_base_url;
$trimmed_uri = strtolower( trim( $this->uri->uri_string, '/'));
if (($trimmed_uri == $uri_prefix.'/index.php' || $trimmed_uri == $uri_prefix) && ($this->default_controller !== FALSE)) {
    // use the default controller if our path is just index.php
    $this->uri->uri_string = '';
}


Note that I am no longer appending '/' to the $uri_prefix to make the comparison work where 'index.php' is not included in the url.

R
Reply with quote
clod
Newbie


Joined: 14 Sep 2009
Posts: 3

PostPosted: Mon Sep 27, 2010 2:16 pm   
 
HI.

I use Codelobster PHP Edition.
It has special plug-in for CodeIgniter.
Reply with quote
mrsteve
Newbie


Joined: 17 Jan 2012
Posts: 1

PostPosted: Tue Jan 17, 2012 10:02 am   re:
 
First I’d suggest you install xampp. Get the full version, because i did it as well.
Then use the dbg installer wizard from nusphere to copy the right debugger file from de PhpED distribution to the php from xampp. They also have instructions int the wizard on how to configure the projects.
ools->Settings->IDE->Run & Debug set Default Browser: Windows Internet Explorer. Use the following Project Properties: Image:Screenshot phped.jpg|left|thumb|300px|screenshot of project properties
Don’t use breakpoints in the code instead insert
DebugBreak();

-----------------
braindumps
Reply with quote
Display posts from previous:   
Post new topic   Reply to topic     Home » Forums » Zugg's Blog All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
© 2009 Zugg Software. Hosted on Wolfpaw.net