XML-RPC实现WebService简单PHP程序示例 及 Closure闭包中的bind与bindTo方法的区别
一、XML-RPC实现WebService简单PHP程序示例
Web Service就是为了异构系统的通信而产生的,它基本的思想就是使用基于XML的HTTP的远程调用提供一种标准的机制,而省去建立一种新协议的需求。目前进行Web Service通信有两种协议标准,一种是XML-RPC,另外一种是SOAP。XML-RPC比较简单,出现时间比较早,SOAP比较复杂,主要是一些需要稳定、健壮、安全并且复杂交互的时候使用。
PHP中集成了XML-RPC和SOAP两种协议的访问,都是集中在xmlrpc扩展当中。另外,在PHP的PEAR中,不管是PHP 4还是PHP 5,都已经默认集成了XML-RPC扩展,而且该扩展跟xmlrpc扩展无关,能够独立实现XML-RPC的协议交互。windows下要使用xmlrpc需要在php.ini中打开:extension=php_xmlrpc.dll;下面是一个xml_rpc客户端发送和服务器端接收处理的程序:
客户端发送程序:页面最下方有程序的下载链接。
#基本 error_reporting(E_ALL); date_default_timezone_set('PRC'); header("Content-type:text/html;charset=utf-8"); #客户端调用实例 $host='localhost'; $port=80; $uri="/InterFace/InterFace.php"; $token=md5($uri); $q='测试'; $Client=new Client($host,$port,$uri); $data=$Client->sendXml('Search',array('token'=>$token,'q'=>$q)); echo "\r \r "; echo '
';print_r($data);echo '';
/**********************************Client Class***********************************/
class Client{
private $host;
private $port;
private $serverUri;
public function __construct($host,$port,$uri){$this->host=$host;
$this->port=$port;
$this->serverUri=$uri;
if(!function_exists("xmlrpc_encode_request")) exit('please install xml-rpc extend first');}
public function sendXml($fun,$params=array()){
$fp=fsockopen($this->host,$this->port);
$request=xmlrpc_encode_request($fun,$params);
$query = "POST {$this->serverUri} HTTP/1.0
User_Agent: XML-RPC Client
Host: ".$this->host."
Content-Type: text/xml
Content-Length:".strlen($request)."".$request."
";
if(!fputs($fp, $query, strlen($query))) {
$errstr = "Write error";
echo $errstr;
return false;
}
$contents = "";
while (!feof($fp)){$contents .= fgets($fp);}
fclose($fp);//显示原始数据
print_r($contents);return $this->AnalyData($contents);
}public function AnalyData($contents){
$pos='';
if(strpos($contents,$pos)===false) exit('ERROR_:'.$contents);
$xml = explode($pos, $contents);
$xml = $pos.array_pop($xml);//测试显示返回数据:
$xml = xmlrpc_decode($xml);
return $xml;
}
}服务器端接收及处理程序:
#基本配置 error_reporting(E_ALL); date_default_timezone_set('PRC'); define('ROOTPATH',str_replace('\','/',dirname(__FILE__)).'/'); $requestXML=file_get_contents('php://input'); //显示服务器接收到的数据 //print_r($requestXML);exit; //需要打开扩展:extension=php_xmlrpc.dll if(!function_exists("xmlrpc_server_create")) { exit('please install xml-rpc extend first'); } //创建xmlrpc_server $xmlrpc_server=xmlrpc_server_create(); xmlrpc_server_register_method($xmlrpc_server,"Search","rpc_server_func"); #数据处理及返回 $xmlrpc_response = xmlrpc_server_call_method($xmlrpc_server, $requestXML, null); header("Content-Type: text/xml"); xmlrpc_server_destroy($xmlrpc_server); //处理函数 function rpc_server_func($method, $params) { $obj = new $method(); echo $obj->dodata($params); } //处理的程序(可统一分离放至单独的处理程序文件夹中 class Search { public function dodata($params) { return xmlrpc_encode('aaa'); } }
下图是数据截图,左边是发送后客户端接收到的数据,右图是服务器端返回给客户端的数据:
不过目前XML应用得很少,现在是json的天下,不过在一些老的系统里还是有很多XML的。XMLRPC实现WebService简单PHP程序示例下载见本博客中的资源下载。–publish:July 21, 2016 -Thursday
二、Closure闭包中的bind与bindTo方法的区别
Closure是PHP里的一个final类,其有两个方法(bind和bindTo),在定义一个闭包函数时实际就是定义了一个Closure的实例化对象。所有所有的闭包函数都自带有bind和bindTo方法:
•Closure::bind — 复制一个闭包,绑定指定的$this对象和类作用域。
•Closure::bindTo — 复制当前闭包对象,绑定指定的$this对象和类作用域。看手册上的描述,很难找到bind和bindTo之间的区别,而事实也的确如此,这两个方法除了在调用方式方法(一个使用::调用,一个使用->调用)不同外,生成的闭包是一样的。相比较而言,bindTo方法是一个更简单的写法。例如我们已经定义了一个闭包$closure,此时我们要得到一个绑定类后的闭包对象,我们有以下三种写法:
//匿名函数绑定到类的写法 $newClosure = Closure::bind($closure, new A(), 'A'); $newClosure = $closure::bind($closure, new A(), 'A'); $newClosure = $closure->bindTo(new A(), 'A');
因为闭包函数$closure本身就是一个Closure,$closure也有bind方法,所有第一种、第二种是一样的,而我们从第二种写法可明显看到重复了一个$closure,这完全没有必要,既然是$closure发起调用bind方法,没必要再将自己做为参数传入,所以第三种写法从上到下可以看出是一种更优的调用方法。
在bind和bindTo的使用上,两者并没有多大差别,如下示例:
//闭包函数Closure中对静态与动态属性的调用 Class Student { static $name = 'kermit'; private $age = 20; } //实例化类,定义匿名函数 $student = new Student(); $getName = function() { return self::$name .'--'.$this->age; }; //将匿名函数绑定到类: $getNameClosure = $getName::bind($getName, $student, 'Student'); echo $getNameClosure(); echo '
'; $otherClosure = $getName->bindTo($student, 'Student'); echo $otherClosure();包括我对各个步骤进行了var_dump打印查看,两个方法生成的闭包对象功能都一样。另外在一系列使用之后,在bind和bindTo的传参上的一些个人总结如下:
1,bind和bindTo的类参数(即上例中的$student)是一个必传参数,如果传null。则闭包函数中不能使用$this,如果传了一个实例化类,闭包函数中才能使用$this。
2,bind和bindTo的类作用域参数(即上例中的’Student’参数)默认为Static,如果使用默认值,则闭包函数中不能使用self调用,如果传了类名,则可以使用self.
3,如果闭包函数存在调用类的private或protected属性或方法,则必须传递第三个参数指明类作用域才能正常调用。