Neither one nor Many
Software engineering blog about my projects, geometry, visualization and music.
Just wanted to use the 'in practice' part because it sounds so cool . 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.
/**
* 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)));
fclose($fd);
// 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")));
fclose($fd);
} else {
if (!isset($_GET['set_state'])) {
// Show index/listing of states
$indexFileLines = array_reverse(explode("\n",
file_get_contents($indexFile)));
foreach ($indexFileLines as $line) {
if (empty($line))
continue;
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);
}
exit(0);
} else {
// Restore a specific state
list ($_SERVER, $_GET, $_POST, $_REQUEST, $_SESSION) =
unserialize(file_get_contents($_GET['set_state'])); //DANGEROUS
}
}
}
statedebugger('E:/TPSC/htdocs/CRMS-Test/webframe/templates_c/');
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...)