近日在項目開發過程中,遇到了在php中使用閉包和回調函數的情況,先看代碼:
function filterAlarmNodes()
{
$category = $this->params["url"]['category'];
$nodesInfo = $this->_getHostsInfo();
$clusterName = $this->Cluster->getClusterName();
$clusterView = $this->health->clusterView($nodesInfo, $clusterName);
$all_hosts = $this->machines->getAllDisplayNames();
//var_dump($clusterView);
$data = array();
foreach ($clusterView as $key => $entry) {
if (!preg_match('/[0-9\.]/', $key))
continue;
$_this = $this;
$callback = function ($category, $key, $entry) use($_this){
return call_user_func(array($_this, '_filterNodes'), $category, $key, $entry);
};
if (($desc = $callback($category, $key, $entry)) != false) {
$data[] = array(
'nodename' => $all_hosts[$this->machines->getHostByIP($key)]['dispname'],
'ip' => $key,
'desc' => $desc
);
}
}
$info = array('code' => 'success', 'data' => $data);
return $this->_jsonView($info);
}
該方法主要用來篩選集群中警告狀態的節點,根據傳入的參數category,返回不同的結果集,例如CPU溫度過高的,CPU利用率過高的等等;由于每個category采用的篩選算法不同,因此定義了一個callback方法,該方法調用$this的_filterNodes方法根據category繼續進行方法分派。定義callback屏蔽了不同篩選方法的差異,外部調用接口始終一致。
function _filterNodes($category, $key, $entry)
{
switch ($category){
case "cpu_temp_alarm":
return $this->_filterNodesForCpuTemp($key, $entry);
case "cpu_usage_alarm":
return $this->_filterNodesForCpuUsage($key, $entry);
default:
break;
}
}
_filterNodesForCpuTemp方法很簡單,根據當前節點采集的各個meter的值(包含在$entry中),返回該節點是否需要包含在篩選結果集中(false為不包含)。在閉包和callback使用中,有兩個地方需要注意:
- _filterNodes不能定義為private,否則回報錯。
- $this不能直接先use($this),然后在回調中使用(php會報錯);需要先把$this賦值給一個變量(本例中是$_this),然后再use($_this),然后在回調方法中使用