[PHP]PHP版的列印變數,可處理遞迴陣列

edited 十月 2013 in 原創軟體分享區
下載點:http://timteam.org/?TIM=FORUM&FORUM=1&ShowDocument=12950#TIM12950

這個列印變數的函式需要PEAR::Date,請先安裝...
目前有一個 bug,就是若有兩個相同結構與內容的陣列,
會把後者是為一個參照,例如範例中的$陣列["X"]和$陣列["Y"]
不知道有沒有人有比較好的算法?

原始討論: http://twpug.net/x/modules/newbb/viewtopic.php?topic_id=187

評論

  • edited 二月 2005
    這個版本有個很"微妙"的順序問題,請看下列程式碼。
    如果把index.php的第56行的註解拿掉,會進入無限迴圈,那兩個變數會被判定成不是同參照。
    但是如果是把69行同樣敘述的註解拿掉,卻又很正常的執行。
    //$陣列["測試"]["BBB"]["xxx"] = &$陣列["測試"]["BBB"];

    function.php
    <?php
    function & 複製(&$變數) {
    	return $變數;
    }
    
    function 名稱結合(&$名稱陣列, $引號 = '', $編碼 = '') {
    	if (false == is_array($名稱陣列) || 0 == count($名稱陣列)) {
    		return '';
    	}
    	$輸出 = $名稱陣列[0];
    	for ($計數 = 1; $計數 < count($名稱陣列); $計數++) {
    		$內容 = $名稱陣列[$計數];
    		$型態 = gettype($編碼);
    		if ('string' == $型態 && is_callable($編碼)) {
    			$內容 = $編碼($內容);
    		} elseif('array' == $型態) {
    			$內容 = strtr($內容, $編碼);
    		}
    		$輸出 .= "[$引號$內容$引號]";
    	}
    	return $輸出;
    }
    
    function 型態(&$變數, $進階 = false) {
    	$型態 = gettype($變數);
    	if (false == $進階) {
    		return $型態;
    	}
    	switch ($型態) {
    	case 'object':
    		$型態 = get_class($變數);
    		break;
    	}
    	return $型態;
    }
    
    function 同參照項目(&$變數, &$項目) {
    	if (is_array($變數) && is_array($項目)) {
    		do {
    			$測試 = uniqid();
    		} while (isset($項目[$測試]));
    		$項目[$測試] = true;
    		$輸出 = !empty($變數[$測試]);
    		unset($項目[$測試]);
    	} elseif (is_object($變數) && is_object($項目)) {
    		do {
    			$測試 = uniqid();
    		} while (isset($項目->$測試));
    		$項目->$測試 = true;
    		$輸出 = !empty($變數->$測試);
    		unset($項目->$測試);
    	} else {
    		$輸出 = false;
    	}
    	return $輸出;
    }
    
    function 同參照(&$變數, &$參照陣列) {
    	$輸出 = null;
    	reset($參照陣列);
    	foreach ($參照陣列 as $名稱 => &$參照) {
    		if (同參照項目($變數, $參照)) {
    			$輸出 = $名稱;
    			break;
    		}
    	}
    	return $輸出;
    }
    
    ?>
    

    debug.php
    <?php
    require_once 'function.php';
    require_once 'Date.php';
    class 除錯 {
    	static private $參照 = null;
    	//private $遞迴 = false;
    	private $內縮 = 0;
    	private $縮進字串 = "\t";
    	
    	private $參照陣列 = array();
    	private $名稱陣列 = array();
    	private $基本型態 = array();
    	private $複合型態 = array('array', 'object');
    	private $引號字元 = array("\"" => '\"');
    
    	private function __construct() {
    		$this->新增型態('Date', 'getDate');
    	}
    	
    	static public function & 參照() {
    		if (null === self::$參照) {
    			self::$參照 = new self;
    		}
    		return self::$參照;
    	}
    	
    	public function 重置() {
    		$this->內縮 = 0;
    		$this->縮進字串 = "\t";
    		$this->除錯陣列 = array();
    		$this->參照陣列 = array();
    		$this->名稱陣列 = array();
    	}
    
    	public function 新增型態($物件名, $顯示函數){
    		if (class_exists($物件名) && is_callable(array($物件名, $顯示函數))) {
    			$this->基本型態[$物件名] = $顯示函數;
    			return true;
    		}
    		return false;
    	}
    
    	private function 變數分析(&$變數) {
    		$型態 = gettype($變數);
    		$輸出 = '';
    		if (false == in_array($型態, $this->複合型態)) {
    			return "($型態) = $變數\n";
    		} else {
    			$物件 = get_class($變數);
    			if (false !== $物件 && array_key_exists($物件, $this->基本型態)){
    				return "($物件) = " . $變數->{$this->基本型態[$物件]}() . "\n";
    			}
    		}
    		$參照 = 同參照($變數, $this->參照陣列);
    		if (0 < $this->內縮 && null !== $參照) {
    			return "($型態) -> ($參照)\n";
    		}
    
    		$this->內縮++;
    		$名稱 = 名稱結合($this->名稱陣列);
    		$this->參照陣列[$名稱] = &$變數;
    		foreach ($變數 as $名 => &$值) {
    			$this->名稱陣列[] = $名;
    			$輸出 .= str_repeat($this->縮進字串, $this->內縮) . "$名 " . $this->變數分析($值);
    			array_pop($this->名稱陣列);
    		}
    		$this->內縮--;
    
    		if ('' != $輸出) {
    			$輸出 = "($型態) = {\n$輸出" . str_repeat($this->縮進字串, $this->內縮) . "}\n";
    		} else {
    			$輸出 = "($型態) = {}\n";
    		}
    		return $輸出;
    	}
    	
    	public function 列印變數(&$變數) {
    		$this->重置();
    		$this->名稱陣列[] = '@';
    		$this->參照陣列['@'] = &$變數;
    		$輸出 = $this->變數分析($變數);
    		return $輸出;
    	}
    }
    
    function & 列印變數(&$變數) {
    	$輸出 = 除錯::參照()->列印變數($變數);
    	return $輸出;
    }
    
    ?>
    

    index.php
    <?php
    mb_internal_encoding('utf-8');
    require_once 'debug.php';
    //require_once 'xml_serializer.php';
    
    ini_set('error_reporting', E_ALL|E_STRICT);
    $測試 = "<?xml version='1.0' ?><!-- 
    <物:物件 />
    <文:字串>字串</文>
    <群:陣列>
    </群>
    <數:數字>100</數>
    <文:正規>/\D/</文>
    <爻:邏輯>陽</爻>
    <時:日期>1104992343531</時>
    <無:null />
    <虛:undefined />
    <虛:void />
    <數:NaN>NaN</數>
    <數:Infinity>Infinity</數>
    <群:測試>
    	<文:AAA>000</文>
    	<群:BBB>
    		<文:zzz>Z</文>
    		<@:xxx>@[測試][BBB]<;/@>;
    		<群:yyy>
    			<@:www>@[測試][BBB]<;/@>;
    			<@:vvv>@[測試][BBB]<;/@>;
    		</群>
    	</群>
    	<@:CCC>@<;/@>;
    	<文:DDD>ABC</文>
    	<@:EEE>@[測試][BBB][yyy]<;/@>;
    	<@:FFF>@[測試][BBB]<;/@>;
    </群>
    -->";
    
    $陣列 = array();
    
    $陣列["物件"] = new stdClass;
    $陣列["字串"] = "字串";
    $陣列["陣列"] = array();
    $陣列["數字"] = 100;
    $陣列["邏輯"] = true;
    $陣列["日期"] = new Date;
    $陣列["null"] = null;
    //$陣列["undefined"] = undefined;
    //$陣列["void"] = void(0);
    //$陣列["NaN"] = NaN;
    //$陣列["Infinity"] = Infinity;
    
    $陣列["測試"] = array();
    $陣列["測試"]["AAA"] = "000";
    $陣列["測試"]["BBB"] = array();
    $陣列["測試"]["BBB"]["zzz"] = "Z";
    //$陣列["測試"]["BBB"]["xxx"] = &$陣列["測試"]["BBB"];
    $陣列["測試"]["CCC"] = &$陣列;
    $陣列["測試"]["DDD"] = "ABC";
    $陣列["測試"]["EEE"] = array();
    $陣列["測試"]["EEE"]["www"] = &$陣列["測試"]["BBB"];
    $陣列["測試"]["BBB"]["yyy"] = &$陣列["測試"]["EEE"];
    $陣列["測試"]["EEE"]["vvv"] = &$陣列["測試"]["BBB"];
    $陣列["測試"]["FFF"] = &$陣列["測試"]["EEE"]["vvv"];
    $陣列["測試"]["EEE"]["vvv"] = &$陣列["測試"]["FFF"];
    //$陣列["測試"]["<>[]!@#$%^&;*()_+|~`\:;,.?\"\'\t\r\n"] = array();
    
    $陣列["測試"]["<>[]!@#$%^&;*(){}_+|~`\:;,.?\"\'\t\r\n"]["TEST"] = "<>[]!@#$%^&;*(){}_+|~`\:;,.?\"\'\t\r\n";
    $陣列["測試"][" "] = &$陣列["測試"]["<>[]!@#$%^&;*(){}_+|~`\:;,.?\"\'\t\r\n"];
    //$陣列["測試"]["BBB"]["xxx"] = &$陣列["測試"]["BBB"];
    
    $測試 = array(
    	'陣列1' => array('1' => 1, '2' => 2),
    	'陣列2' => array('1' => 1, '2' => 2),
    );
    
    $測試01 = array(
    	'陣列1' => array('1' => 1, '2' => 2, '3' => &$測試01),
    	'陣列2' => array('1' => 1, '2' => 2),
    );
    
    $測試01['陣列2']['3'] = &$測試01['陣列2'];
    //$序列化 = 序列化($陣列, true);
    //$序列化 = 序列化($測試);
    //$前置分析 = 前置分析($序列化);
    //$反序列化 = 反序列化($序列化);
    //$反序列化 = 反序列化($測試);
    echo '<pre>';
    if (同參照項目($陣列['測試']['BBB']['xxx'], $陣列['測試']['BBB'])) {
    	echo "同參照 = true<br>";
    } else {
    	echo "同參照 = false<br>";
    
    }
    echo "<hr>列印變數測試:\n";
    echo htmlspecialchars(列印變數($陣列));
    //print_r($陣列);
    /*
    echo '<hr>';
    echo htmlspecialchars(列印變數($測試));
    echo '<hr>';
    echo htmlspecialchars(列印變數($測試01));
    */
    echo "<hr>序列化測試:\n";
    //echo htmlspecialchars($序列化);
    echo "<hr>前置分析測試:\n";
    //echo htmlspecialchars(列印變數($前置分析));
    echo "<hr>反序列化測試:\n";
    //echo htmlspecialchars(列印變數($反序列化, true));
    //echo htmlspecialchars(列印變數($反序列化));
    echo '</pre>';
    
    ?>
    
Sign In or Register to comment.