[Tip] Debugging Your Plugin - how to save time and frustration
by
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 https://en.wikipedia.org/wiki/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 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: Code:
[client 77.57.16.130] PHP Parse error: parse error, unexpected ')' in /home/.sites/81/site18/web/online.php(135) : eval()'d code on line 13, referer: http://www.englishforum.ch/online.php?order=asc&sort=username&pp=30&page=1 [client 77.57.16.130] PHP Parse error: parse error, unexpected ')' in /home/.sites/81/site18/web/online.php(135) : eval()'d code on line 13, referer: http://www.englishforum.ch/online.php?order=asc&sort=username&pp=30&page=1 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 https://en.wikipedia.org/wiki/Integrated_development_environment (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 http://www.waterproof.fr, 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 https://www.phpmyadmin.net - 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: Code:
$uname = $vbulletin->usersinfo['username']; if ($uname == "mark") { $foo = 'bar'; } if ($foo == "bar") { // routine to change our template here } Code:
$uname = $vbulletin->usersinfo['username']; print 'uname was set to: ' . $uname . '\n'; if ($uname == "mark") { print 'We entered the first conditional'; $foo = 'bar'; print 'foo was set to: ' . $foo . '\n'; } if ($foo == "bar") { print 'We entered the second conditional'; // routine to change our template here } print 'We are done'; Code:
uname was set to: We are done Code:
uname was set to: mark We entered the first conditional foo was set to: bar We entered the second conditional We are done 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: Code:
if ($vbulletin->userinfo['userid'] == 1) { // my plugin code here } 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: Code:
include_once(DIR . '/includes/devtools.php'); Rather than using the print statement, I use a function called print_log(). Here's a copy of the function: Code:
function print_log($string) { global $vbulletin; // to assist with debugging $file = fopen(DIR . "/stats/devlog.log", "a"); fwrite($file, date("d.m.Y H:i:s") . " " . $vbulletin->userinfo['username'] . " " . $string . "\n"); fclose($file); } Code:
print_log('foo was set to: ' . $foo); Code:
30.06.2007 07:43:01 mark foo was set to: bar 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 http://aidanlister.com/repos/v/function.hexdump.php, 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: Code:
print_log(dump_hex($vbulletin->templatecache['WHOSONLINE'])); Code:
0000 24 73 74 79 6c 65 76 61 72 5b 68 74 6d 6c 64 6f $styleva r[htmldo 0010 63 74 79 70 65 5d 0d 0a 3c 68 74 6d 6c 20 64 69 ctype].. <html di 0020 72 3d 5c 22 24 73 74 79 6c 65 76 61 72 5b 74 65 r=\"$sty levar[te 0030 78 74 64 69 72 65 63 74 69 6f 6e 5d 5c 22 20 6c xtdirect ion]\" l 0040 61 6e 67 3d 5c 22 24 73 74 79 6c 65 76 61 72 5b ang=\"$s tylevar[ 0050 6c 61 6e 67 75 61 67 65 63 6f 64 65 5d 5c 22 3e language code]\"> 0060 0d 0a 3c 68 65 61 64 3e 0d 0a 24 68 65 61 64 69 ..<head> ..$headi When viewing hex dumps I highly recommend using an http://www.goascii.com/. 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: Code:
printlog(dump_hex($vbulletin->templatecache['WHOSONLINE'], true)); Code:
1 2 3 4 5 6 7 8 12345678901234567890123456789012345678901234567890123456789012345678901234567890 0 $stylevar[htmldoctype]..<html dir=\"$stylevar[textdirection]\" lang=\"$stylevar[ 80 languagecode]\">..<head>..$headinclude..$metarefresh..<title>" . $GLOBALS['vbull 160 etin']->options['bbtitle'] . " - $vbphrase[whos_online]</title>..</head>..<body> 240 ..$header..$navbar....".(($pagenav) ? ("..<table cellpadding=\"0\" cellspacing=\ 320 "0\" border=\"0\" width=\"100%\" style=\"margin-bottom:3px\">..<tr valign=\"bott 400 om\">...<td align=\"$stylevar[right]\">$pagenav</td>..</tr>..</table>..") : ("") 480 )."....<table class=\"tborder\" cellpadding=\"$stylevar[cellpadding]\" cellspaci 560 ng=\"$stylevar[cellspacing]\" border=\"0\" width=\"100%\" align=\"center\" id=\" 640 woltable\">..<tr>...<td class=\"tcat\" colspan=\"$colspan\"><div class=\"smallfo 720 nt\">....<span style=\"float:$stylevar[right]\">.....<a href=\"$reloadurl\"><str 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 https://en.wikipedia.org/wiki/Breakpoint 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? |
Similar Mods
Administrative and Maintenance Tools Save+Reload for plugin editor | vBulletin 3.7 Add-ons |