Qik Stream
-
PHP RemoteObjects
No CommentsCzasem potrzebujemy użyć kawałka kodu PHP będącego na innej maszynie. Sięgamy wtedy po xmlrpc czy inne wynalazki takie jak CURL czy zdalne file_get_contents. Na nasze głowy spada wtedy przetworzenie danych przed wysłaniem i po odebraniu. Do tego jedno wywołanie z reguły oznacza całkowite wykonanie kodu po drugiej stronie. A czasem przydałoby się coś na raty zrobić.
Przedstawione poniżej klasy pozwalają na zdefiniowanie serwera obiektów. Obiekt taki można z poziomu klienta utworzyć na serwerze i korzystać potem z niego jak z obiektu lokalnego, wywoływać metody, odwoływać się do pól. Każda taka operacja okupiona jest wywołaniem HTTP do serwera, więc należy tego używać z umiarem.
Oto kod klasy klienta:
class RPC_Client { private $server=false; private $token=false; function __construct($server=false) { if($server) { $this->server=$server; } $ret=$this->__call('__construct',array()); return $ret; } function __call($method,$params) { $call['method']=$method; $call['params']=$params; $call['token']=$this->token; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $this->server); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, array('call'=>serialize($call))); $ret_string = curl_exec($ch); if(curl_errno($ch)) { print curl_error($ch); } curl_close($ch); $ret=unserialize($ret_string); $this->token=$ret['token']; if(isset($ret['exception'])) { throw unserialize($ret['exception']); } return $ret['data']; } function __set($key,$value) { $params['key']=$key; $params['value']=$value; return $this->__call('__set',$params); } function __get($key) { $params['key']=$key; return $this->__call('__get',$params); } }
Kod klasy serwera:
class RPC_Server { private $server=false; private $data=array(); function __construct() { $ret=array(); $query_str=trim($_SERVER['QUERY_STRING']); $query=explode('=',$query_str); $class=array_shift($query); $call=unserialize(stripslashes($_POST['call'])); $method=$call['method']; $params=$call['params']; $token=$call['token']; // odkomentowac, jesli nie jest zdefiniowana funkcja __autoload // if(!class_exists($class)) // { // require_once('class/'.$class.'.class.php'); // } $memcache = new Memcache; $memcache->connect('localhost', 11211) or die ("Could not connect"); if(!$token) { $token=md5(getmypid().time()); $obj=new $class (); } else { $obj=$memcache->get($token); } $ret['token']=$token; try { $ret['data']=@call_user_func_array(array(&$obj,$method),$params); } catch(Exception $e) { $ret['exception']=serialize($e); } $memcache->set($token,$obj); echo serialize($ret); } }
Klasa macierzysta dla klas serwowanych:
class RPC { private $data=array(); function __set($key,$value) { return $this->data[$key]=$value; } function __get($key) { return $this->data[$key]; } }
Przykład klasy serwowanej:
class RPC_Test extends RPC { public $aaa=10; function __construct() { return 'RPC_Test ready'; } function mul($x,$y) { return $x*$y; } function except() { throw new Exception('Hello!'); } function spl($string) { return explode(' ',$string); } }
Oraz serwera:
$srv = new RPC_Server();
I klienta:
$srv = new RPC_Client('http://localhost/~zibi/src/RPCServer.php?RPC_Test'); echo $srv->mul(10,11)); $srv->val=10; echo $srv->val; $srv->val+=20; echo $srv->val; $srv->tekst='jaki wiekszy tekscik coby bylo co obrabiac'; echo var_dump($srv->spl($srv->tekst));

Recent Comments