[PHP]変数を展開して画面表示する自作関数echoecho() Ver.007 の公開

Read More


渡された変数、配列、文字列などを展開し画面表示するDolem独自関数のechoecho()。
挙動が安定してきたので先にこちらで公開する。

使い方は第一引数に展開したい変数や配列を渡すだけ。

■echoecho()の使い方
$a = array (1, 2, array ("a", "b", "c"));
echoecho($a);


上記は以下のように画面出力される。
画面イメージ



--
■echoecho() Ver.007
/**
 * ★変数、配列などを展開し格納された情報を画面出力する:開発デバッグ用
 * ****************************************40
 * 第1引数に指定された変数を展開し画面出力する。
 * 第1引数では変数、配列、オブジェクト、文字列、数値などを渡すことが可能となっている。
 * 
 * 第2引数では展開した変数を識別するための文字列を指定することができる。
 * 第2引数が無指定の時は第1引数を動的に名前取得する。ただし取得が不可能な場合は表示名がunknownとなる。
 * 
 * 第1引数が未指定の場合は全てのスーパーグローバル変数の情報を出力する。
 * この出力は1プロセス中で1度のみ実行可能。
 * 
 * ex) $sampleの中身を展開して出力する
 *     $sample = 1;
 *     echoecho($sample);
 * 
 * ex) 全てのスーパーグローバル変数を展開する
 *     echoecho();
 *     
 * 注意)
 *  画面出力された文字列(特にSQLクエリ)を直接範囲選択しコピーすることがあると想定している。
 *  この為展開されたものにコピーに不都合なエスケープシーケンスは行わない。
 *  変更しているエスケープシーケンスは以下の通り。
 *  「\'」=>「'」、「\\」=>「\」
 *  string型、又は配列の値がstring型のものは、値の前後が文字列を表す「'(クォート)」で挟まれているにも関わらず、中の文字列はエスケープされない点に注意する必要がある。
 * 
 * 007 - 2016/11/24 xirasaya: 一行に複数回本関数が呼ばれた場合など自動名前取得の精度が不安定なものは名前をunknownにする。
 *  また表示名では一切のエスケープをしないことで挙動を統一する。
 * 006 - 2013/03/28 xirasaya: 第1引数の表示名取得の精度を上げた。かなり力技。
 *  またトレース表示を関数呼び出し元のファイルパス一つのみに変更した。ただしそれが本関数の定義されたファイルだった場合はその次のものを表示する。
 * 005 - 2012/07/02 xirasaya: 第1引数を指定した状態で第2引数を省略した時、本来表示名として利用される第2引数を動的に取得するよう変更。
 *  ただしこの機能は、現段階では本関数を1行で2回以上呼び出しをすると表示名を正しく取得できない。この問題は第2引数をきちんと指定すれば回避できる。
 *  また以前は、第1引数が未指定(又はnull)で、かつ第2引数が未指定(又はnull)の場合のみ全てのスーパーグローバル変数の情報を出力するというものだったが、Ver.005からは引数が無指定(void)の時のみ全てのスーパーグローバル変数の情報を出力するように変更。
 *  またこれ以外の出力時においては、呼び出し元ファイル名と呼び出し元の行番号が表示されるように変更。
 *  HTMLのstyle属性を若干変更。
 * 004 - 2012/04/26 xirasaya: 英字が続くと画面横に伸びる問題を解消。
 * 003 - 2011/06/16 xirasaya
 * 001 - 2007/10/31 xirasaya
 * @param variant $var=null 
 * @param string  $sName=null
 * @return void
 */
function echoecho($var=null, $sName=null)
{
  static $_call_flg=null;
  
  $aryTrace = debug_backtrace();
  $aryLine = file($aryTrace[0]['file']);
  $sLine = $aryLine[($aryTrace[0]['line']-1)];
  
  /** 第二引数を展開する */
  if(isset($sName))
  {
    $sName = var_export($sName, true);
  }
  /** 第二引数に名前がない場合動的に名前取得を試みる */
  elseif(preg_match_all('/(echoecho[\s]*\(.*?\))/u', $sLine, $matches))
  {
    if(isset($matches[1]) and count($matches[1])===1)
    {
      if(preg_match('/echoecho[\s]*\((.+)\)/u', $sLine, $match))
      {
        $quote = (preg_match('/^\'/u', $match[1]))? '\'':null;
        $buf = str_getcsv($match[1], ',', '\'', '\\');
        $sName = $quote.$buf[0].$quote;
      }
    }
    else
    {
      $sName = 'unknown';
    }
  }
  
  if(!isset($var) and !isset($sName) and !isset($_call_flg))
  {
    $_call_flg=true;
    @echoecho($_GET);
    @echoecho($_POST);
    @echoecho($_REQUEST);
    @echoecho($_SESSION);
    @echoecho($_COOKIE);
    @echoecho($_ENV);
    @echoecho($_FILES);
    @echoecho($_SERVER);
    @echoecho(array_keys($GLOBALS), 'GLOBALS key');    // $GLOBALSの再帰呼び出しはしない
    @echoecho(get_included_files());    // インクルードされたファイル順で表示
    $defines = get_defined_constants(true);
    @echoecho($defines['user'], 'defines');        // ユーザ定義定数を表示
    unset($defines);
  }
  else
  {
    
    if(is_resource($var))
    {
      $sType = ' (ResourceType: '. get_resource_type($var).')';
      $sVar = $var;    // リソース型はhtmlspecialchars()を使うとwarningになる。var_export()を使うとnullになる。
    }
    else
    {
      $sType = ' (DataType: '. gettype($var).')';
      $buf = var_export($var, true);
      $buf = str_replace('\\\'', '\'', $buf);    // var_export()の仕様で戻り値が「\'」となるのを「'」にする
      $buf = str_replace('\\\\', '\\', $buf);    // var_export()の仕様で戻り値が「\\」となるのを「\」にする
      $sVar = htmlspecialchars($buf);
    }// end if
    $sOutput = '<fieldset style="border:1px solid #000;background-color:#eee;padding:0px 10px;margin:20px 0 20px 0;font-size:13px;">';
    $sOutput.= '<legend style="color:#ff0000;font-weight:bold;text-align:left;">[&nbsp;'. htmlspecialchars($sName). '<span style="color:#888;font-weight:normal;">'. htmlspecialchars($sType). '</span>&nbsp;]</legend>';
    $sOutput.= '<div style="color:#000;font-weight:normal;padding:0;text-align:left;">';
    $sOutput.= '<pre style="white-space: pre-wrap;word-wrap: break-word;margin:10px 0;">';
    $sOutput.= '<div style="margin-bottom:4px;">'.$sVar.'</div>';
    if(is_array($aryTrace))
    {
      $disp_control=1;
      foreach($aryTrace as $key => $val)
      {
        if(isset($val['file']) and isset($val['line']))
        {
          if($val['file']!=__FILE__ and $disp_control==1)
          {
            $sOutput.= '<div style="font-size:10px;color:#888;margin-bottom:-5px;">'. htmlspecialchars($val['file']).'('.htmlspecialchars($val['line']).')</div>';
            $disp_control=0;
          }
        }
      }
    }
    $sOutput.= '</pre>';
    $sOutput.= '</div></fieldset>';
    echo $sOutput;
  }
}




開発速度を上げるために存在する関数という位置づけ。
コード内に複数埋め込むと動きをトレースするのに楽。

なお埋め込みすぎるとたまに消すのを忘れるので注意。



--
そのうちDolemにも反映する予定。
そのうち、そのうち…



-- 2016/11/25
円マークとクォートの表示がおかしくなっていたのを修正