PHP Conference Japan 2024

var_export

(PHP 4 >= 4.2.0, PHP 5, PHP 7, PHP 8)

var_export輸出或返回變數的可解析字串表示

說明

var_export(混合類型 $value, 布林值 $return = false): ?字串

var_export() 會取得指定變數的結構化資訊。它與 var_dump() 類似,但有一個例外:回傳的表示法是有效的 PHP 程式碼。

參數

value

您想要輸出的變數。

return

如果使用並設定為 truevar_export() 將會回傳變數表示法,而不是輸出它。

回傳值

return 參數被使用且評估為 true 時,會回傳變數表示法。否則,此函式將回傳 null

更新日誌

版本 說明
8.2.0 輸出的類別名稱現在是完整限定名稱;先前會省略開頭的反斜線。
7.3.0 現在會將 stdClass 物件輸出為轉換成物件的陣列 ((object) array( ... )),而不是使用不存在的方法 stdClass::__setState()。實際效果是現在 stdClass 可以被輸出,而且產生的程式碼甚至可以在較舊版本的 PHP 上運作。

範例

範例 #1 var_export() 範例

<?php
$a
= array (1, 2, array ("a", "b", "c"));
var_export($a);
?>

以上範例會輸出

array (
  0 => 1,
  1 => 2,
  2 => 
  array (
    0 => 'a',
    1 => 'b',
    2 => 'c',
  ),
)
<?php

$b
= 3.1;
$v = var_export($b, true);
echo
$v;

?>

以上範例會輸出

3.1

範例 #2 輸出 stdClass (自 PHP 7.3.0 起)

<?php
$person
= new stdClass;
$person->name = 'ElePHPant ElePHPantsdotter';
$person->website = 'https://php.dev.org.tw/elephpant.php';

var_export($person);

以上範例會輸出

(object) array(
   'name' => 'ElePHPant ElePHPantsdotter',
   'website' => 'https://php.dev.org.tw/elephpant.php',
)

範例 #3 輸出類別

<?php
class A { public $var; }
$a = new A;
$a->var = 5;
var_export($a);
?>

以上範例會輸出

A::__set_state(array(
   'var' => 5,
))

範例 #4 使用 __set_state()

<?php
class A
{
public
$var1;
public
$var2;

public static function
__set_state($an_array)
{
$obj = new A;
$obj->var1 = $an_array['var1'];
$obj->var2 = $an_array['var2'];
return
$obj;
}
}

$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';

eval(
'$b = ' . var_export($a, true) . ';'); // $b = A::__set_state(array(
// 'var1' => 5,
// 'var2' => 'foo',
// ));
var_dump($b);
?>

以上範例會輸出

object(A)#2 (2) {
  ["var1"]=>
  int(5)
  ["var2"]=>
  string(3) "foo"
}

注意事項

注意:

這個函式無法匯出 resource 類型的變數。

注意:

var_export() 不會處理循環引用,因為要產生可解析的 PHP 程式碼幾乎是不可能的。如果您想對陣列或物件的完整表示做一些處理,請使用 serialize()

警告

在 PHP 8.2.0 之前,當 var_export() 匯出物件時,為了最大的相容性,命名空間類別的類別名稱中不會包含前導反斜線。

注意:

為了能夠評估由 var_export() 產生的 PHP 程式碼,所有被處理的物件都必須實作魔術方法 __set_state。唯一的例外是 stdClass,它會使用轉型為物件的陣列來匯出。

參見

新增註解

使用者貢獻的註解 21 則註解

steven at nevvix dot com
5 年前
我改進了我之前的 varexport()。

<?php
/**
* 使用縮排兩個空格的短陣列語法 (方括號) 的 PHP var_export() 函式。
*
* 注意:唯一的問題是,當字串值包含 `=>\n[` 時,它會被轉換為 `=> [`
* @link https://php.dev.org.tw/manual/en/function.var-export.php
*/
function varexport($expression, $return=FALSE) {
$export = var_export($expression, TRUE);
$patterns = [
"/array \(/" => '[',
"/^([ ]*)\)(,?)$/m" => '$1]$2',
"/=>[ ]?\n[ ]+\[/" => '=> [',
"/([ ]*)(\'[^\']+\') => ([\[\'])/" => '$1$2 => $3',
];
$export = preg_replace(array_keys($patterns), array_values($patterns), $export);
if ((bool)
$return) return $export; else echo $export;
}

$array = [
'str' => 'Test
spaces'
,
0 => 33,
1 => TRUE,
[
3,4,'d',[]],
'arr' => [
'text with spaces' => '[Tes\'t"s":
=> [
=>
[
{
spaces'
,
],
"str2" => "Test's'
} spaces"
,
'arr2' => [
'text with spaces' => [
'arr3' => [
'text with spaces' => 'Te": "st \' => [
spaces'
,
],
],
],
];
varexport($array);
// 結果:
```
[
'str' => 'Test
spaces',
0 => 33,
1 => true,
2 => [
0 => 3,
1 => 4,
2 => 'd',
3 => [
],
],
'arr' => [
'text with spaces' => '[Tes\'t"s":
=> [
=> [
{
spaces',
],
'str2' => 'Test\'s\'
} spaces',
'arr2' => [
'text with spaces' => [
'arr3' => [
'text with spaces' => 'Te": "st \' => [
spaces',
],
],
],
]
```
注意唯一的問題是當字串值包含 `=>\n[` 時,它會被轉換為 `=> [`
steven at nevvix dot com
6 年前
/**
* 使用方括號和 4 個空格縮排的 var_export() 函式。
*/
<?php
function varexport($expression, $return=FALSE) {
$export = var_export($expression, TRUE);
$export = preg_replace("/^([ ]*)(.*)/m", '$1$1$2', $export);
$array = preg_split("/\r\n|\n|\r/", $export);
$array = preg_replace(["/\s*array\s\($/", "/\)(,)?$/", "/\s=>\s$/"], [NULL, ']$1', ' => ['], $array);
$export = join(PHP_EOL, array_filter(["["] + $array));
if ((bool)
$return) return $export; else echo $export;
}
Mark P
8 年前
雖然似乎沒有被記錄,但 `var_export()` 的行為在 PHP 7 中有所改變。

先前,`var_export(3.)` 會回傳 "3",現在則回傳 "3.0"。
chudinov at yahoo dot com
11 年前
看起來自 5.4.22 版起,var_export 使用 serialize_precision ini 設定,而不是用於一般浮點數輸出的 precision 設定。
因此,從 5.4.22 版開始,例如 var_export(1.1) 將輸出 1.1000000000000001(17 是預設的精確度值),而不是像之前的 1.1。

<?php
//輸出 1.1000000000000001
var_export(1.1)
?>
4n4jmza02 at sneakemail dot com
14 年前
我吃過苦頭才學到,如果 var_export 遇到資源控制代碼,它會將其匯出為「NULL」,即使它是有效的控制代碼。 文件說明控制代碼無法匯出,但沒有說明如果仍然嘗試這樣做會發生什麼事。

我在追蹤資源控制代碼未產生問題的過程中,在一些除錯程式碼中使用了 var_export,結果卻誤以為在問題解決後,仍然產生了空的控制代碼。
dan at coders dot co dot nz
10 年前
我發現我的複雜類型匯出時會出現
stdClass::__set_state()
在某些地方。這不僅奇怪又混亂,而且根本無法用 eval() 重新帶入。會發生致命錯誤。真糟糕!

然而,快速地將結果中的字串替換清理後,就可以使其再次有效。

$macro = var_export($data, TRUE);
$macro = str_replace("stdClass::__set_state", "(object)", $macro);
$macro = '$data = ' . $macro . ';';

現在我輸出的字串*可以*再次用 eval() 重新帶入了。
laszlo dot heredy at gmail dot com
14 年前
當您只想了解目前頁面上設定的變數值時,請嘗試使用以下函式,而不是 var_export($GLOBALS) 或 var_dump($GLOBALS)。

<?php
function globalvars(){
$result=array();
$skip=array('GLOBALS','_ENV','HTTP_ENV_VARS',
'_POST','HTTP_POST_VARS','_GET',
'HTTP_GET_VARS',
'_COOKIE',
'HTTP_COOKIE_VARS','_SERVER',
'HTTP_SERVER_VARS',
'_FILES','HTTP_POST_FILES',
'_REQUEST','HTTP_SESSION_VARS',
'_SESSION');
foreach(
$GLOBALS as $k=>$v)
if(!
in_array($k,$skip))
$result[$k]=$v;
return
$result;
}
//functionglobalvars

var_export(globalvars());
?>
linus at flowingcreativity dot net
19 年前
<roman at DIESPAM dot feather dot org dot ru>,您的函式效率低落且存在問題。當我要求您在將程式碼新增到手冊之前先進行測試時,我可能是在替所有人發聲。

由於空格問題僅在匯出陣列時才會出現,因此您可以將原始的 var_export() 用於所有其他變數類型。這個函式可以完成這項工作,而且從外部來看,其作用與 var_export() 相同。

<?php

function var_export_min($var, $return = false) {
if (
is_array($var)) {
$toImplode = array();
foreach (
$var as $key => $value) {
$toImplode[] = var_export($key, true).'=>'.var_export_min($value, true);
}
$code = 'array('.implode(',', $toImplode).')';
if (
$return) return $code;
else echo
$code;
} else {
return
var_export($var, $return);
}
}

?>
NitPicker
11 年前
當涉及到 HTML 輸出時(如下所述),一切都很有趣,直到有人被「<」戳到眼睛。

用「<pre>」把它包起來,但也請記得用 htmlspecialchars() 包裝它。
beverasrilakshmi at gmail dot com
5 年前
只是好玩,試圖理解「返回可解析字串」的定義....任何傳遞給 var_export 的變數類型,返回值都將被類型轉換為字串...

<?php

$var
= 1;
var_dump($var); //類型是預期的 int
echo "<br>";
$var_after_export = var_export($var,true); //返回 $var 現在會使其成為字串
var_dump($var_after_export);

?>
john dot risken at gmail dot com
14 年前
我在使用者筆記中任何地方都沒看到這個簡單的小項目。也許我眼瞎了!

無論如何,var_export 和 print_r 都使用空格和換行符號進行格式化。發送到 html 頁面時,大部分格式化都會丟失。這個簡單的函數將格式良好的陣列打印到 html 螢幕上

<?php
function pretty_var($myArray){
print
str_replace(array("\n"," "),array("<br>","&nbsp;"), var_export($myArray,true))."<br>";
}
?>
Glen
17 年前
如同先前報告的,我發現 var_export() 在處理遞迴結構時令人沮喪。執行

<?php
var_export
($GLOBALS);
?>

會失敗。有趣的是,var_dump() 有一些邏輯可以避免遞迴引用。所以

<?php
var_dump
($GLOBALS);
?>

可以運作(雖然比較醜)。與 var_export() 不同,var_dump() 沒有返回字串的選項,因此如果您想導向輸出,則需要輸出緩衝邏輯。
ravenswd at gmail dot com
15 年前
(這取代了我 2009 年 7 月 3 日的筆記。原始版本如果變數包含空陣列或僅由空陣列組成的陣列,則不會產生任何輸出。例如,$bigarray['x'] = array(); 此外,我還添加了該函數的第二個版本。)

在查看具有多個層級且每個層級上都有許多元素的陣列時,輸出可能難以辨認。例如

<?php
print ('$bigarray = ' . var_export($bigarray, true) . "\n");
?>

會回傳

$bigarray = array(
... (略過 500 行) ...
'mod' => 'charlie',

而以下例程可以這樣呼叫

<?php
recursive_print
('$bigarray', $bigarray);
?>

它會回傳

$bigarray = array()
... (略過 500 行) ...
$bigarray['foo']['bar']['0']['somethingelse']['mod'] = 'charlie'

函式如下

<?php
function recursive_print ($varname, $varval) {
if (!
is_array($varval)):
print
$varname . ' = ' . $varval . "<br>\n";
else:
print
$varname . " = array()<br>\n";
foreach (
$varval as $key => $val):
recursive_print ($varname . "['" . $key . "']", $val);
endforeach;
endif;
}
?>

如果需要產生有效的 PHP 程式碼,請使用這個版本

<?php
function recursive_print ($varname, $varval) {
if (!
is_array($varval)):
print
$varname . ' = ' . var_export($varval, true) . ";<br>\n";
else:
print
$varname . " = array();<br>\n";
foreach (
$varval as $key => $val):
recursive_print ($varname . "[" . var_export($key, true) . "]", $val);
endforeach;
endif;
}
?>

如果輸出到文字檔而不是 HTML 網頁,請移除 <br>。
sergei dot solomonov at gmail dot com
12 年前
<?php
$closure
= function(){};

var_export($closure);

// 輸出:Closure::__set_state(array())
?>
jodybrabec at gmail dot com
12 年前
「巢狀層級過深 - 遞迴相依」錯誤的解決方法
ob_start();
var_dump($GLOBALS);
$dataDump = ob_get_clean();
echo $dataDump;
匿名
13 年前
有一個更簡單的方法可以在 HTML 頁面中取得 var_export 和 print_r 的乾淨輸出

<?php
function pretty_var($myArray)
{
echo
"<pre>";
var_export($myArray);
echo
"</pre>";
}
?>
stangelanda at arrowquick dot com
17 年前
我一直在尋找將資料儲存在快取檔案中的最佳方法。

首先,我發現了 var_export 與 serialize 的兩個限制。它無法儲存陣列內部的內部參考,並且在 PHP 5.1.0 之前無法儲存巢狀物件或包含物件的陣列。

然而,我可以處理這兩種情況,所以我建立了一個基準測試。我使用了一個包含 10 到 150 個索引的單個陣列。我使用布林值、空值、整數、浮點數和一些巢狀陣列(巢狀陣列平均較小,為 5 個元素,但建立方式類似)隨機產生元素的值。大部分元素是 10-15 個字元左右的短字串。雖然有少量長字串(大約 500 個字元)。

基準測試返回了 1000 * [總時間] / [迭代次數(在這種情況下為 4000)] 的這些結果

serialize 3.656, 3.575, 3.68, 3.933, 平均值 3.71
include 7.099, 5.42, 5.185, 6.076, 平均值 5.95
eval 5.514, 5.204, 5.011, 5.788, 平均值 5.38

這意味著對於單個大型陣列,serialize 的速度比 var_export 快大約 1.5 倍。 include 和 eval 的表現始終非常接近,但 eval 通常快十分之幾秒(eval 在這組特定的測試中比平常表現更好)。像 APC 這樣的 opcode 快取可能會使 include 更快,但除此之外,serialize 是最佳選擇。
paul at worldwithoutwalls dot co dot uk
20 年前
對於資源變數,var_export() 與 print_r() 不同,如果您將該函數用於除錯目的,print_r() 會更有用。
例如:
<?php
$res
= mysql_connect($dbhost, $dbuser, $dbpass);
print_r($res); //輸出:資源 id #14
var_export($res); //輸出:NULL
?>
me at peterkooi dot com
28 天前
一個用於將變數導出為字串的小函數,支援巢狀陣列,具有縮排輸出、區塊引用和雙引號,可以貼回程式碼中。

<?php
函式 dump($value) {
函式
_dump($value, $indent = 0) {
如果 (!
is_array($value)) 返回 json_encode($value, JSON_NUMERIC_CHECK);
foreach(
$value 作為 $key => $item) $result .= (isset($result) ? ",\r\n" . str_repeat(" ", $indent + 2) : "") . json_encode($key) . " => " . _dump($item, $indent + 2);
返回
"[\r\n" . str_repeat(" ", $indent + 2) . "$result\r\n" . str_repeat(" ", $indent) . "]";
}
返回
"<pre>" . htmlspecialchars(_dump($value)) . "</pre>";
}
php_manual_note at bigredspark dot com
21 年前
[john holmes]
沒錯,但該方法需要您打開文件並將其讀入一個變數,然後再將其反序列化到另一個變數。

使用 var_export() 建立的文件可以簡單地使用 include() 引入,這樣程式碼更少且速度更快。

[kaja]
如果您正在嘗試尋找一種方法來將變數暫時儲存到其他文件中,請查看 serialize() 和 unserialize() - 這個方法更適用於其可讀性,在除錯時非常方便。

[原始文章]
如果您像我一樣,您可能會想知道為什麼一個輸出「正確 PHP 語法」的函式很有用。這個函式在實現快取系統時很有用。您可以使用 var_export() 將陣列輸出到一個變數中,並將其寫入到一個文件中。編寫如下字串

<?php
$string
= '<?php $array = ' . $data . '; ?>';
?>

其中 $data 是 var_export() 的輸出,可以建立一個可以輕鬆使用 include() 引入回腳本以重新建立 $array 的文件。

var_export() 的原始輸出也可以使用 eval() 重新建立陣列。

---John Holmes...
rarioj at gmail dot com
15 年前
注意:如果物件 Foo 具有 __set_state() 方法,但如果該物件包含另一個沒有實現 __set_state() 方法的物件 Bar,則產生的 PHP 表達式將無法使用 eval() 執行。

這是一個例子(包含 Exception 實例的物件 Test)。

<?php

類別 測試
{
公用
$一;
公用
$二;
公用 函式
__construct($一, $二)
{
$this->= $一;
$this->= $二;
}
公用 靜態 函式
__set_state(陣列 $陣列)
{
回傳 new
self($陣列['一'], $陣列['二']);
}
}

$測試 = new 測試('一', new 例外('測試'));

$字串 = var_export($測試, );

/* $字串 =
測試::__set_state(陣列(
'一' => '一',
'二' =>
例外::__set_state(陣列(
'message' => '測試',
'string' => '',
'code' => 0,
'file' => 'E:\\xampp\\htdocs\\test.Q.php',
'line' => 35,
'trace' =>
陣列 (
),
'previous' => NULL,
)),
))
*/

eval('$測試2 = '.$字串.';'); // 致命錯誤:呼叫未定義的方法 例外::__set_state

?>

因此,避免在包含其他物件的複雜陣列/物件上使用 var_export()。請改用 serialize() 和 unserialize() 函式。

<?php

$字串
= 'unserialize('.var_export(serialize($測試), ).')';

eval(
'$測試2 = '.$字串.';');

var_dump($測試 == $測試2); // 布林值(真)

?>
To Top