-
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