Watcher: PHP Session Variables Tracker
        
<?php
  ////////////////////////////////////////////////////////////////////////////
  // watcher.php
  //
  // utility to display current session vars for PHP troubleshooting, with
  //   output a bit more organized than print_r(); to use, open new tab in
  //   the same browser running the application which is generating/using
  //   the session vars of interest; default behavior is to display all
  //   active session vars; a session variable prefix may be provided as a
  //   GET parm to display only those vars; for example,
  //
  //       http://mywebsite.com/watcher.php?prefix=test_
  //
  //   will retrieve and display only those vars at the topmost level which
  //     begin with "test_"
  //
  // output is Web page showing all matching session vars and their values; 
  //   arrays are nested, color-coded, and recursively expanded; because the 
  //   arrays are walked recursively, there is no practical limit on the 
  //   levels to which the arrays may be nested (although the display may get 
  //   funky if nested too deep); the output page is not particularly pretty, 
  //   but this is intended only as a development tool, not a polished Web page
  //
  // note the display order is the same as the creation order; the PHP
  //   function ksort() could be used to make locating a specific item
  //   by key name easier
  //
  // Written 11/27/2010, L.Pritchett, Cliffson Solutions, LLC
  // Revised 2/21/2015, L.Pritchett, Cliffson Solutions, LLC
  ////////////////////////////////////////////////////////////////////////////
  session_start();
  //==========================================================================
  // global constants
  //==========================================================================
  // colors are used in sequence, wrapping back to the first color if nesting
  //   exceeds the number of defined colors; colors may be added, deleted, or 
  //   modified freely with no change in the code below; if color coding of
  //   each level is not desired, remove all colors but one
  $aCOLORS = array ("blue", "green", "crimson", "magenta", "brown", "orange",
    "black");
  // indent in pixels for each array level in displayed page
  define("iINDENT_DISPLAY", 20);
  // indent for HTML code itself (makes for easier troubleshooting)
  define("iINDENT_HTML", 2);
  //==========================================================================
  //  functions
  //==========================================================================
  function fnDisplay_Var($sname, $sval, $ilevel)
  {
    // display given var/val pair; indent HTML code appropriately
    // handle special cases: turn NULLs and Booleans into something printable, 
    //   add quotes to strings
    if (is_null($sval))
      $sval = "NULL";
    else if (is_bool($sval))
      $sval = $sval ? "true" : "false";
    else if (is_string($sval))
      $sval = sprintf("\"%s\"", $sval);
    printf("%s%s => %s\n", str_repeat(" ", $ilevel * iINDENT_HTML), 
      htmlspecialchars($sname), htmlspecialchars($sval));
    printf("%s<br />\n", str_repeat(" ", $ilevel * iINDENT_HTML));
  }
  function fnWalk_Array($sname, $oval, $ilevel)
  {
    // recursive function to walk all elements of array and display
    //   each member, indenting each new level and changing the display
    //   color for easier tracking
    global $aCOLORS;
    if (is_array($oval))
    {
      // write array name at current indent level
      printf("%s%s =>\n", str_repeat(" ", $ilevel * iINDENT_HTML), 
        htmlspecialchars($sname));
      // create new indented div with new text color
      $ilevel++;
      printf("%s<div style=\"margin-left:%dpx;color:%s;\">\n",
        str_repeat(" ", $ilevel * iINDENT_HTML), iINDENT_DISPLAY, 
        $aCOLORS[$ilevel % count($aCOLORS)]);
      // walk through all elements of array, calling this function
      //   recursively if any of those are also arrays
      foreach ($oval as $schild_name => $ochild_val)
        fnWalk_Array($schild_name, $ochild_val, $ilevel);
      printf("%s</div>\n", str_repeat(" ", $ilevel * iINDENT_HTML));
    }
    else
    {
      // if not array, write var/val pair and end recursion
      fnDisplay_Var($sname, $oval, $ilevel);
    }
    return;
  }
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  <title>PHP Session Reporter</title>
</head>
<body>
<center>
  <h3>Current Session Variables</h3>
<?php
  // create refresh button; could be eliminated, as a browser refresh works
  //   just as well
  printf("  <button onclick=\"document.location='%s%s'\">\n",
    $_SERVER['SCRIPT_NAME'], (!empty($_SERVER['QUERY_STRING']) &&
    ($_SERVER['QUERY_STRING'] != "clear=true")) ?
    "?" . $_SERVER['QUERY_STRING'] : "");
  printf("    Refresh\n");
  printf("  </button>\n");
  printf("  <button onclick=\"document.location='%s%s?clear=true'\">\n",
    $_SERVER['SCRIPT_NAME'], (!empty($_SERVER['QUERY_STRING']) &&
    ($_SERVER['QUERY_STRING'] != "clear=true")) ?
    "&" . $_SERVER['QUERY_STRING'] : "");
  printf("    Clear\n");
  printf("  </button>\n");
?>
  <hr />
</center>
<br />
<br />
<?php
  //==========================================================================
  // start inline code
  //==========================================================================
  // if clear option selected, do that first
  if (!empty($_GET['clear']))
    foreach ($_SESSION as $sVar => $sVal)
      unset($_SESSION[$sVar]);
  if (empty($_SESSION))
    printf("  No session variables are currently defined\n");
  else
  {
    // start primary block in 1st color
    printf("<div style=\"color:%s;\">\n", $aCOLORS[0]);
    foreach($_SESSION as $sName => $oVal)
    {
      // if prefix specified, only display variables that match; note this
      //   screening is only done on 1st layer variable names, not on
      //   array members or their descendents
      if (empty($_GET['prefix']) || (strpos($sName, $_GET['prefix']) === 0))
      {
        if (is_array($oVal))
          fnWalk_Array($sName, $oVal, 0);
        else
          fnDisplay_Var($sName, $oVal, 0);
      }
    }
    printf("</div>\n");
  }
?>
</body>
</html>