iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 11
0
自我挑戰組

花式PHP系列 第 12

Object:Pass By Reference By Default

物件傳到哪參考到哪?!

你知道在函式的參數前面加上「&」就可以達成 Pass by reference 吧?

但你知道在 PHP 裡面,
Object 是不管怎麼傳都是 Pass by reference 嗎?

舉例來說,
底下這段程式碼執行完之後,$obj->key 會是 value 還是 12345678 呢?

<?php

function assign($obj, $key, $value)
{
    $obj->{$key} = $value;
}

$obj = new stdClass;
$obj->key = 'value';

assign($obj, 'key', '12345678');

print_r($obj);

大家只要把這程式碼拿去執行就知道答案了!


離真相還有一段距離

根據 PHP 官方的說法
說 Object 這東西預設就是 Pass by reference 是不完全對的說法。

怎麼說呢?
從 PHP 5 之後,每當你在 new 一個 Object 的時候,
其實你宣告的變數得到的並非 Object 本身,而是得到對 Object 的參考


所以**「參考」傳到哪都是參考**,只不過 PHP 可以用它來找到參考指向的 Object

也因此,如果改寫上面的範例,
讓 assign 函式在修改資料之後把 Object 回傳,
並比較原 Object,及修改後的 Object,
會發現它們其實還是一樣的。

<?php

function assign($obj, $key, $value)
{
    $obj->{$key} = $value;
    
    return $obj;
}

$obj = new stdClass;
$obj->key = 'value';

$alteredObj = assign($obj, 'key', '12345678');

echo $obj->key === $alteredObj->key ? 'true' : 'false';

建立物件的複本

除非對傳入 Object 執行 clone,PHP 才知道你要的並非傳入 Object 的參考,而是它的複本:

<?php

function assign($obj, $key, $value)
{
    $obj = clone $obj;
    
    $obj->{$key} = $value;
    
    return $obj;
}

$obj = new stdClass;
$obj->key = 'value';

$alteredObj = assign($obj, 'key', '12345678');

echo $obj->key === $alteredObj->key ? 'true' : 'false';

希望今天的內容可以幫助到你,
讓你能避免浪費許多踩雷及 debug 的時間~


上一篇
Array:Compact & Extract
下一篇
Laravel:深入config:cache
系列文
花式PHP31

尚未有邦友留言

立即登入留言