近日在项目开发过程中,遇到了在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),然后在回调方法中使用