Neither one nor Many

January 14 2011

Just wanted to use the 'in practice' part because it sounds so cool img1. At work I used to have some cool tricks I'd use at customers (test-environments) or local setups to debug. One of my favourite snippets I use all the time is the following.

Record and re-create requests..

 * Debug helper function for logging and restoring requests. Do not use in 
 * production environments.
 * - Logs the URL and request data.
 * - With __STATE_DEBUGGER__ parameter in the URL it displays a listing
 *   of logged requests.
 * - Clicking an item in that listing, re-creates that request.
 * I know it is usually not good practice to have *one* function do multiple 
 * things. Make sure you know what you're doing ;)
 * @param writableDirectory directory for saving the requests in files
 * @return void (call it solely for it's side-effects ;-))
function statedebugger($writableDirectory = '/tmp')
    if (!is_dir($writableDirectory) || !is_writable($writableDirectory)) {
        trigger_error('parameter writableDirectory needs to exist and be
            writable', E_USER_ERROR);
    $indexFile = $writableDirectory . '/index.txt';
    if (!isset($_GET['__STATE_DEBUGGER__'])) {
        // Write state file for request
        $stateFileName = tempnam($writableDirectory, 'p');
        $fd = fopen($stateFileName, 'wb');
        fwrite($fd, serialize(array($_SERVER, $_GET, $_POST, $_REQUEST,
            !isset($_SESSION) ? array() : $_SESSION)));
        // Rewrite index
        $indexFileContents = file_exists($indexFile) ?
            file_get_contents($indexFile) : '';
        $fd = fopen($indexFile, 'wb');
        fwrite($fd, implode(array($indexFileContents, //INEFFICIENT
            $stateFileName, ' ', $_SERVER['REQUEST_URI'], "\n")));
    } else {
        if (!isset($_GET['set_state'])) {
            // Show index/listing of states
            $indexFileLines = array_reverse(explode("\n",
            foreach ($indexFileLines as $line)  {
                if (empty($line))
                list($filename, $requestUri) = explode(" ", $line);
                printf("<a href=\"%s%s__STATE_DEBUGGER__&set_state=%s\">%s</a><br/>\n",
                    $requestUri, (strpos($requestUri, "?") === FALSE ? "?" :
                                    "&"), $filename, $requestUri);
        } else {
            // Restore a specific state
            list ($_SERVER, $_GET, $_POST, $_REQUEST, $_SESSION) =
                unserialize(file_get_contents($_GET['set_state'])); //DANGEROUS

Just paste that in the config, or whatever global headerfile (your software probably has), and it logs all requests to some specified directory. Usually when something goes wrong within a very specific context (a specific user with rights, session variables, page, ..), it would be nice to just log the requests (e.g. with post data), and use that information to re-create the (failing) request. So you can keep pressing F5 in your browser window while fixing the bug. This function does that. Also this can be especially useful when debugging AJAX requests, i.e. without firebug, or you can let the user create the very specific context (with privileges and user settings) that causes some failure, and in that way create the test-case.

(Add __STATE_DEBUGGER__ to the URL as a parameter, and it will show a listing with clickable requests. Clicking redirects to that page and initializes it with the recorded $_GET, $_POST, $_SESSION, ...)

(By the way I didn't bother to make this very secure (see file_get_contents($_GET['set_state']) for example), because this should only be used when debugging. This could easily be improved with some numerical parameters, optional descriptions, limit to fixed number of requests...)

Webdevelopment Comments (0)

Leave a Reply

Comment may not be visible immediately, because I process everything manually.**

**) I plan to automate this.., but it's on my ToDo since for ever..

Ray Burgemeestre
february 23th, 1984

C++, Linux, Webdev

Other interests:
Music, Art, Zen