2015-05-19 46 views
5

我有一個鏈調用像這樣的字符串鏈通話功能:如何通過使用含有鏈PHP

$object->getUser()->getName(); 

我知道我可以使用一個字符串來調用一個對象上的功能:

$functionName = 'getUser'; 
$object->$functionName() or call_user_func(array($object, functionName)) 

我想知道是否有可能爲連鎖電話做同樣的事情? 我試圖做的:

$functionName = 'getUser()->getName'; 
$object->functionName(); 

但我得到一個錯誤

方法名稱必須是一個字符串

我想這是因爲()->不能因爲它們解釋是字符串的一部分?有沒有什麼辦法可以做到這一點,而不必做:

$function1 = getUser; 
$function2 = getName; 
$object->$function1()->$function2(); 

目的是獲得功能的陣列,並把它們連,以調用給定對象上這條產業鏈,如:

$functions = array('getCoordinates', 'getLongitude'); // or any other chain call 
$functionNames = implode('()->',$functions); 
$object->$functionNames() 
+0

在你的類方法中,通過'return $ this;''返回當前類。 – Akar

+1

@Voitcus你能舉個例子嗎? – skirato

+0

@Akar我不明白你是什麼意思... – skirato

回答

13

讓我們先從一個較爲中性的文本格式,很容易處理:

$chain = 'getUser.getName'; 

,然後簡單地reduce它:

$result = array_reduce(explode('.', $chain), function ($obj, $method) { 
    return $obj->$method(); 
}, $object); 

請注意,您甚至可以檢查$obj以確定$method是否爲方法或屬性,甚至數組索引和return的值是否適當。請參閱Twig以獲取靈感。

+1

不錯,但'explode'可以使用多個字符串作爲分隔符,所以''>' – Voitcus

+0

沒有問題是的,但是目標是從一個與語言無關的表達式開始,而不是PHP-代碼 - as-串。 – deceze

1

我想創建一個過濾對象和數組的通用方式。有時候,這種過濾需要鏈式調用來將特定字段與給定值進行比較。

我認爲,不要發明新的解決方案,您可以使用Symfony的PropertyAccess Component等現有的解決方案。