Register Members List Search Today's Posts Mark Forums Read

Article Options
[Tip] Debugging Your Plugin - how to save time and frustration
Join Date: Mar 2007
Posts: 336

I run a forum for English-speaking people in Switzerland

Zurich, Switzerland
by mfyvie mfyvie is offline 03 Jul 2007

Debugging Your Plugin - how to save time and frustration

Have you ever tried to write a plugin (or any piece of code) and been frustrated when it doesn't work? If you've been doing this for a while you've no doubt got your own debugging techniques. But when you are starting out, you probably don't really know what to do.

The purpose of this tutorial is to try to "jump start" your debugging approach. It's mostly aimed at people who are just beginning to write their own plugins. Adopting some form of debugging technique can save you significant time. I wish I'd done it from the very beginning!

Before we discuss various debugging techniques, let's consider the types of error situations we may encounter. Then we'll look at ways of avoiding or fixing them. We can divide our errors up into two broad categories:
  • Syntax or parsing errors - PHP doesn't like the format of what you've written
  • Database errors - bad queries will usually throw up an error on the user's browser. This is usually very bad
  • Logic errors - Your program will run, but it won't do what you expect it to
Different errors require different approaches and different tools.

Syntax or parsing errors

In many ways these are the easiest errors to deal with, because PHP will immediately write an entry to your error log. If you are going to be writing plugins, you need to get access to your error log to check if there are syntax or parsing errors.

Your error log depends on your webserver. If you are using apache on linux you'll usually find it in /var/logs/httpd/error_log. It's a good idea to use a command like tail -f /var/log/httpd/error_log to "follow" the log in real time. You can then have the log in one window and load the page on your forum in another. This way you can see immediately if there are any errors.

What will an error look like? Here's an example:
Block Disabled:      (Update License Status)  
Suspended or Unlicensed Members Cannot View Code.

These error messages can be very useful, in that they contain information to help you narrow down the problem. First of all the error seems to be about an unexpected ')'. Chances are that we've forgotten to put a '(' somewhere else in our statement. If you aren't sure what the error means, google it. There's other important information here, namely the file we were running, in this case online.php. The number in brackets (135) is the line number of online.php where the error occurred. If we look at that line we see it is the hook for online_start. Since you are debugging just after writing your plugin, you probably don't need to know which hook you are using. The important information follows: eval()'d code on line 13. This means that the error is found on line 13 of our plugin.

Bear in mind that the error was encountered on line 13, but the cause may actually lie one or two lines before that. If you forget a semicolon for example, the error usually shows up on the following line.

What if you are on a shared server and you don't have access to the error log? You need to talk to your hosting provider and see if they can somehow provide this information to you (in real time). If not, then you are going to have to install vBulletin on another machine (like your own PC) and do your development work on the local machine. You can find a tutorial on how to do this here.

A better way is to avoid syntax or parsing errors altogether by using a PHP IDE (Integrated Development Environment), in other words, a PHP editor application with built-in syntax checking (an IDE does a lot more, but I'm trying to keep the explanation simple). I use phpedit, but there are many others. This allows me to write directly in the editor and if there are any syntax or parsing errors they are underlined immediately. This means I can ensure that my code is error free, then I paste it into the plugin and test it.

You may also ask if you can break your forum with a syntax error in one of your plugins. Usually the answer to this is no, since the entire plugin won't execute. However, if there something in the plugin that is required by a plugin, which executes later and needs the information for say a database query, this could cause a problem if the value is not set. We'll cover database errors shortly.

Regardless of whether you are doing error checking in a PHP editor, it's still an idea to keep an eye on your error log, especially if you were developing a plugin on your production system (which of course you would never do, right? No of course, not - never).

Database errors

These tend to be show-stoppers. The user will be presented with a big page in their browser explaining that mysql has produced an error and nothing else will happen. It will give the error details directly in the browser though. You need to act quickly, especially if this is affecting every page on your forum. Go back and disable your plugin and ensure that your pages load again, and then to try figure out the problem. If you have your system set up to email the database errors to you, check your email inbox. If this feature isn't set up, then go to your vBulletin settings under "Error Handling & Logging" and check.

The good news is that you'll get a copy of the query that caused the error, along with the approximate point that mysql objected to. If you can't see the error straight away try and copy and paste the failed query from the error message into a tool like *link phpmyadmin (which allows you to submit queries directly), or use the execute query option in the admincp under "Maintenance". I prefer something like phpmyadmin - if you don't have it you should install it or ask your hosting provider to provide access for you.

Fixing mysql query errors is beyond the scope of this document, you'll have to google for the correct syntax, or look for other tutorials on building sql queries.

Logic errors

These are the hardest types of errors to track down. They usually don't produce any error messages, but you don't get the results you expect. If you are working with a series of conditional statements or variables which rely on other variable values, you need to verify that the variables contain the values that you want and that conditionals are branching in the way you expect. Let's consider a small routine:
Block Disabled:      (Update License Status)  
Suspended or Unlicensed Members Cannot View Code.

When we run our plugin while logged in, our template didn't change the way we wanted it to. Maybe we have a problem with the routine that changes the template, but since that is going to be harder to debug, let's first try and figure out if we actually got to the point where that routine was supposed to be executed. After confirming that you have no syntax or parsing errors (see above), you may wish to alter your routine like this:
Block Disabled:      (Update License Status)  
Suspended or Unlicensed Members Cannot View Code.

By using the print statement our text will be output directly to the browser. This should be seen as a "quick and dirty" method, and usually not desirable since users may end up seeing this information on the pages they load. We'll look at a better method in a minute, but for the meantime let's examine the output from this routine:
Block Disabled:      (Update License Status)  
Suspended or Unlicensed Members Cannot View Code.

What about the rest? Now we know that we never made it into either conditional. Why not? Because $uname never contained the value we expected. So obviously we should find out why that didn't happen and examine the line immediately above. You probably already spotted the error - we used $vbulletin->usersinfo['username'] rather than $vbulletin->userinfo['username']. Once we remove the offending "s" and rerun our plugin, this is now what we see:
Block Disabled:      (Update License Status)  
Suspended or Unlicensed Members Cannot View Code.

That's better. Did our template edit work? If it did - we are happy. If it didn't, then at least we know we have to debug the next statements and that we did arrive at the template change routine as we expected to.

By using this technique you can save yourself a lot of head scratching. It's much better to know exactly where your program is going and what values are being placed in variables rather than guessing. But printing to the browser is not a very elegant way to test things, especially in a production environment, so let's look at a few ways to make our development and testing process a little more elegant.

Limiting the execution of your plugin

During the testing phase, why have your plugin executed by everybody? If you have used the print statement (as in the example above), then it would be better that they never see the output. Also, if you introduce errors or break logic that affects other parts of your forum then this may affect other functions in an unexpected way. But of course, you'd never develop or test on a production forum, would you? Whenever I'm testing something new I usually wrap the whole plugin in something like this:

Block Disabled:      (Update License Status)  
Suspended or Unlicensed Members Cannot View Code.

This is extremely simple and means that the plugin will only run whenever I happen to load that page (since my userid is 1), but not for anyone else.

Loading in some additional functions during development

Do you have a little tool kit of functions that make life easier when developing? Why not load them at the top of your plugin during the development and testing phase, then remove them when you are finished. I load my extra functions by inserting this line at the top of each of my plugins:
Block Disabled:      (Update License Status)  
Suspended or Unlicensed Members Cannot View Code.

This file contains the functions I use. If I need a new function, I simply insert it into this file. I've attached a sample of this file to the end of this tutorial containing the two functions about to be covered.

Rather than using the print statement, I use a function called print_log(). Here's a copy of the function:

Block Disabled:      (Update License Status)  
Suspended or Unlicensed Members Cannot View Code.

It's very simple, and just keeps a running log with whatever I want. I can then watch this log in realtime with tail -f ./stats/devlog.log if I like (for those running linux). Using it within my program is really simple. To take an example from above it would look something like this:

Block Disabled:      (Update License Status)  
Suspended or Unlicensed Members Cannot View Code.

This will give me an output something like this:
Block Disabled:      (Update License Status)  
Suspended or Unlicensed Members Cannot View Code.

Note that the date, time and username were added here by the function itself, but you can customise this with whatever you like. Now you can have your all your debug information going to a separate log. This means you can log information about live user sessions easily, without anyone seeing anything in their browser.

Another tool which can be very useful is the dump_hex() function, which is also included in my devtools.php file. I originally copied this routine from this page, but have since extended it to add some more functionality (like an ASCII dump mode and the ability to change the numbers of columns and column widths).

You can look inside the function itself to see the various options, but here's a sample of what happens if I combine it with print_log. Imagine you want to see exactly what is inside a template - not how it is presented to you in the editor, but what is really stored. You might do something like this:

Block Disabled:      (Update License Status)  
Suspended or Unlicensed Members Cannot View Code.

Here's a sample of the first part of the output:
Block Disabled:      (Update License Status)  
Suspended or Unlicensed Members Cannot View Code.

Now you can easily discover all the "hidden" characters if you are trying to a search and replace. For example, look at the last line - did you see the values "0d 0a"? These are carriage return and linefeed characters (new line). If you were looking at them in the template editor, you'd simply see a new line, but what if you wanted to locate or replace text with str_replace() within the template? Viewing a hex dump of variables or other data be very helpful sometimes. The other advantage is that you can also output non-printable characters (like binary data). The value in hexadecimal will be shown, but if the character can't be displayed in ASCII, you'll just see a dot character instead.

When viewing hex dumps I highly recommend using an ASCII table. If this is new to you, look up the codes 0d, 0a, 09 (13, 10, and 09 in decimal respectively) and see what they are. Could these be useful characters to spot in a hex dump?

What if we wanted to see the same thing but without the hex information? We could feed an extra parameter to dump_hex to show only the ASCII side, with a wider column. Let's try this:

Block Disabled:      (Update License Status)  
Suspended or Unlicensed Members Cannot View Code.

Our output is now formatted differently, with a ruler along the top.

Block Disabled:      (Update License Status)  
Suspended or Unlicensed Members Cannot View Code.

Note that if we were trying to locate special characters (like tab or new line), this wouldn't be very useful, but for all ASCII printable characters, it will be.

Advanced debugging techniques

The best way to debug is with a proper set of debugging tools like those found in a PHP IDE (Integrated Development Environment). This allows you to step through the code, set breakpoints and display variable values at various points inside your program. However, if you were already using this type of debugging, you wouldn't be reading nor need this tutorial. Therefore a discussion about this is out of scope for this document.

Some more small development hints

There might be times when you just want to try out various bits of PHP code. Rather than experimenting inside a plugin, it makes more sense to write and perfect your routines in a small standalone program. If you haven't already installed PHP on your home machine, do so. If you are running vBulletin on a server and you have shell access to that server, you probably have access to the PHP command line executable. Type "php" and see what happens. If so, you can write small programs in a text editor and run them on the server.

You can extend this concept further and actually make small PHP pages that hook into vbulletin. There is an excellent tutorial on this here. It's very easy and it means you can access vBulletin variables and classes from within a totally separate file. This makes certain types of testing very easy and worry-free.

Remember that testing small routines in a proper PHP editor with good debugging tools is the easiest option. You can use the advanced debugging features to step through your code. When it's ready - try it as a plugin in your vBulletin environment.

What next?

Hopefully this tutorial will help you debug your vBulletin plugins more quickly. Do you have any other useful functions or techniques that you use on a regular basis when debugging for vBulletin? Why not share them with us?
Attached Files
File Type: php devtools.php (4.0 KB, 147 views)

Last edited by mfyvie; 07 Jul 2007 at 14:16.. Reason: adding attachment
Views: 10180
Reply With Quote
Old 03 Jul 2007, 22:23
Paul M's Avatar
Paul M Paul M is offline
Join Date: Sep 2004
Real name: Paul M
Nice Article, moved to vbulletin articles.
Former Staff Member

Cable Forum
Please do not PM me about custom work - I no longer undertake any.
Note: I will not answer support questions via e-mail or PM - please use the relevant thread or forum.
Reply With Quote
Old 26 Jul 2007, 02:59
Antivirus's Avatar
Antivirus Antivirus is offline
Join Date: Sep 2004
Very nice! Well - written
Please feel free to PM me about custom work, installations, and upgrades!

Eclipse Records - Streetcult Street Team
Reply With Quote
Old 19 Aug 2008, 22:19
TCattitude's Avatar
TCattitude TCattitude is offline
Join Date: Oct 2004
Never seen this before. Thanks for the tips and sharing
Reply With Quote
Old 20 Aug 2008, 14:44
Triky's Avatar
Triky Triky is offline
Join Date: Mar 2007
Location: [Italy]
I'm italian, I am learning english.. so, please, if you see any errors in my grammar or spelling, let me know via PM. Danke!
Reply With Quote

Similar Article
Article Author Type Replies Last Post
Administrative and Maintenance Tools Save+Reload for plugin editor Carnage vBulletin 3.7 Add-ons 8 21 Sep 2008 15:24

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
Article Options

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

New To Site? Need Help?

All times are GMT. The time now is 03:45.

Layout Options | Width: Wide Color: