用 SplObjectStorage 來避免無窮迴圈

Written by Simon Asika on

SplObjectStorage 是一個方便我們儲存物件,並確認是否曾經儲存過的工具,無須煩惱物件的名稱。例如:

$storage = new SplObjectStorage;

$o1 = new StdClass;
$o2 = new StdClass;
$o3 = new StdClass;

$s->attach($o1);
$s->attach($o2);

var_dump($s->contains($o1));
var_dump($s->contains($o2));
var_dump($s->contains($o3));

結果會是:

bool(true)
bool(true)
bool(false)

也可以移除一個物件:

$s->detach($o2);

var_dump($s->contains($o1));
var_dump($s->contains($o2));
var_dump($s->contains($o3));
bool(true)
bool(false)
bool(false)

這有個好處,我們可以直接用這個物件在巢狀處利事務時避免無窮迴圈,例如:

public function dump($data, $storage = null)
{
    if (!$storage)
    {
        $storage = new SplObjectStorage
    }

    $dump = new StdClass;

    foreach ((array) $data as $field => $value)
    {
        // Do not dump the property if it has already been dumped.
        if (!$storage->contains($value))
        {
            // Call self
            $dump->$field = $this->dump($value, $storage);

            $storage->attach($value);
        }
        else
        {
            $dump->$field = '* RECURSIVE *';
        }
    }

    return $dump;
}

非常簡單,剩下的大家自行發揮吧。

Control Tools

WS-logo