PHPRPC for PHP

Install PHPRPC for PHP

Uncompress PHPRPC for PHP releases on the fly,

  • bigint.php
  • compat.php
  • phprpc_date.php
  • xxtea.php

These 4 files are common files which are required by both server and client side.

  • phprpc_client.php

This is the client code, if you need PHPRPC for PHP client only, common files and this file are enough for you, include this file in your client code only, common files are included implicitly.

  • dhparams
  • dhparams.php
  • phprpc_server.php

These files are required by PHPRPC server.
dhparams folder includes parameters which will be used to generate private key in encrypted mode, if you need detailed explaination, see Encrypted transfer.

dhparams.php includes a class to access dhparams directory.
phprpc_server.php is PHPRPC for PHP server, if you are going to publish services by PHP, you should include this file, common files and dhparams.php will be included implicitly.

Runtime environmonet

  • PHP 4.3+, PHP 5, PHP 6
  • PHPRPC client requires socket extension
  • PHPRPC server requires HTTP server with PHP support, such as IIS, apache, lighttpd
  • Session must be configured properly, if encrypted mode is enabled

bigint extenstion is recommeneded to enable when encrypt is enabled, gmp, big_int, bcmath are supported by PHPRPC (ordered by performance). If your host doesn't support these extensions, key exchange will be done by php script, it is a bit slower.

For better encryption performance, xxtea PECL extension should be enabled, it is written in C programming language, this extension can significantly improve encryption performance.

How to compile xxtea extension

There are three popular ways to do this:

  1. Compiled with PHP source code
  2. Use phpize
  3. Use Microsfot Visual C (.net or 6.0) on Windows

1. compile with PHP source code

  1. Create ext/xxtea in PHP source code root path, move all files to this folder
  2. Run <span style="font-family: Arial;">./buildconf</span> to create PHP configure script
  3. Compile PHP with <span style="font-family: Arial;">--enable-xxtea</span> flag, this will create a xxtea internal module, using <span style="font-family: Arial;">--enable-xxtea=shared</span> flag instead will create a dymanical extension.

2. phpize utility

  1. Uncompress xxtea extension source code achive
  2. Run <span style="font-family: Arial;">phpize</span>, this will create configure script and other stuff required
  3. Run <span style="font-family: Arial;">./configure --enable-xxtea=share</span> to generate a proper makefile
  4. Run <span style="font-family: Arial;">make</span> to compile xxtea extension
  5. <span style="font-family: Arial;">make install</span>, this will install xxtea extension to PHP

3. Use Microsoft Visual C (.net or 6.0)

  1. Create ext/xxtea in PHP source code root path, move all files to this folder
  2. Copy php4ts.lib (for PHP 4) or php5ts.lib (for PHP 5) from current working PHP directory to ext/xxtea.
  3. Open php_xxtea.sln or php_xxtea.dsw, compile Release_php4 or release_php5
  4. Copy php_xxtea.dll from ext/xxtea/Release_php4 or ext/xxtea/Release_php5 to PHP extension directory, the path of extension directory can be found in php.ini
  5. add this line to php.ini: <span style="font-family: Arial;">extension=php_xxtea.dll</span>
 
PHPRPC for PHP Server

Publish functions

In Quick start chapter, we already knew how to register a php function, in the following text, we are going to know which functions can be published as PHPRPC services.
Most functions can be published, even php internal functions, except the functions which have resource type parameters or return values (such as mysql_connect, mysql_query).
You can even publish several functions at one time, no matter your own functions or php internal ones. For example:


  1. <?php  
  2. include('php/phprpc_server.php');  
  3. function hello($name) {  
  4.     return 'Hello ' . $name;  
  5. }  
  6. $server = new PHPRPC_Server();  
  7. $server->add(array('hello''md5''sha1'));  
  8. $server->add('trim');  
  9. $server->start();  
  10. ?> 

In this case, we published 4 functions, hello is the one we created, the other three are php internal functions. We can place the function names into an array, add method can accept function names as string and array both.

Publish methods

Class static methods and instance methods are supported as well, for example:

  1. <?php  
  2. include('php/phprpc_server.php');  
  3. class Example1 {  
  4.     static function foo() {  
  5.         return 'foo';  
  6.     }  
  7.     function bar() {  
  8.         return 'bar';  
  9.     }  
  10. }  
  11. $server = new PHPRPC_Server();  
  12. $server->add('foo''Example1');  
  13. $server->add('bar'new Example1());  
  14. $server->start();  
  15. ?> 

foo is a class method, the second parameter is the class name. bar is an instance method, so the second parameter should be an instance of class. If you publish an instance method by the way of class method, you will get a warning error when calling. 1

Maybe we want to ask how to publish 2 methods with the names belonging to different classes? Will they conflict? How to avoid conflict?

Alias

It does, this happens usally, In some cases, the functions registered later may overwrite the one registered before, PHPRPC provide alias mechanism to solve this problem, see following code:

  1. <?php  
  2. include('php/phprpc_server.php');  
  3. function hello($name) {  
  4.     return 'Hello ' . $name;  
  5. }  
  6. class Example1 {  
  7.     static function foo() {  
  8.         return 'foo';  
  9.     }  
  10.     function bar() {  
  11.         return 'bar';  
  12.     }  
  13. }  
  14. class Example2 {  
  15.     function foo() {  
  16.         return 'foo, too';  
  17.     }  
  18.     function bar() {  
  19.         return 'bar, too';  
  20.     }  
  21. }  
  22. $server = new PHPRPC_Server();  
  23. $server->add('hello', NULL, 'hi');  
  24. $server->add('foo''Example1''ex1_foo');  
  25. $server->add('bar'new Example1(), 'ex1_bar');  
  26. $server->add(array('foo''bar'), new Example2(), array('ex2_foo''ex2_bar'));  
  27. $server->start();  
  28. ?> 

Both functions and methods can be registered with alias. To register a function, the second parameter should be set as NULL. To add several methods/functions at one time, the number and order of alias should match the functions/methods list.

NOTE, the original name of the functions/methods are not callable, only alias can be used.

Use Session

In the above example, we did publish an instance method, but we didn't use $this to access instance members in code. It is unusual actaully, it looks like a class static method except it will get warning by called as static methods". You should find it don't work as expected when trying to access instance members in it, for example:

  1. <?php  
  2. include('php/phprpc_server.php');  
  3. class ExampleCounter {  
  4.     var $_count = 0;  
  5.     function inc() {  
  6.         $this->_count += 1;  
  7.     }  
  8.     function count() {  
  9.         return $this->_count;  
  10.     }  
  11. }  
  12. $server = new PHPRPC_Server();  
  13. $server->add(array('inc''count'), new ExampleCounter());  
  14. $server->start();  
  15. ?> 

We published two instance methods of ExampleCounter, but no matter how many times inc called by clients, count always returns 0.

It is caused by the way of PHP execution. The server side pages are loaded again everytime you call them. So, a new ExampleCount instance will be created everytime, and destoried with all page content.

If you want to use instances like local resources, you can add instances to sessions, for example:

  1. <?php  
  2. include('php/phprpc_server.php');  
  3. class ExampleCounter {  
  4.     var $_count = 0;  
  5.     function inc() {  
  6.         $this->_count += 1  
  7.     }  
  8.     function count() {  
  9.         return $this->_count;  
  10.     }  
  11. }  
  12. if (!isset($_SESSION['counter'])) {  
  13.     $_SESSION['counter'] = new ExampleCounter();  
  14. }  
  15. $server = new PHPRPC_Server();  
  16. $server->add(array('inc''count'), $_SESSION['counter']);  
  17. $server->start();  
  18. ?> 

By this way, you will get expected result when calling from clients, you can operate session in instances as well.

  1. <?php  
  2. include('php/phprpc_server.php');  
  3. class ExampleCounter {  
  4.     function ExampleCounter() {  
  5.         if (!isset($_SESSION['count'])) {  
  6.             $_SESSION['count'] = 0;  
  7.         }  
  8.     }  
  9.     function inc() {  
  10.         $_SESSION['count'] += 1;  
  11.     }  
  12.     function count() {  
  13.         return $_SESSION['count'];  
  14.     }  
  15. }  
  16. $server = new PHPRPC_Server();  
  17. $server->add(array('inc''count'), new ExampleCounter());  
  18. $server->start();  
  19. ?> 

That's exactly what we do when developing PHP dynamic pages. If you need application scope instead of session scope, database and Memcache can help, they are out of topic, we won't talk about them here.

Publishment options

Services publishment has several options, in most cases, you don't need to worry about them, the default values should be the best. Here is an example of options:

  1. <?php  
  2. include('php/phprpc_server.php');  
  3. function hello($name) {  
  4.     return 'Hello ' . $name;  
  5. }  
  6. $server = new PHPRPC_Server();  
  7. $server->add('hello');  
  8. $server->setCharset('UTF-8');  
  9. $server->setDebugMode(true);  
  10. $server->setEnableGZIP(true);  
  11. $server->start();  
  12. ?> 

setCharset is a method used to set charset, the default value is 'UTF-8', if you need other charsets, you need to call this method, UTF-8 is one of the best choice for internationalization.

setDebugMode decide whether your servre is running in debug mode. In debug mode, the published methods will return more detailed information, including filenames, lines. Generally speaking, in production site, this options should be turned off, it is secure for your web server, so the default value is false.

setEnableGZIP is used to turn on/off gzip compression. GZIP compresson can reduce the number of bytes transmitted, but it costs more memory and CPU, so the default value is off. Actually, many web servers (such as Apache, lighttpd, nginx) provide GZIP compression, we don't need to turn it on in general.
You won't see the warning error, because it won't popup like a dialog box, it is visible in programming level only, you will find it when you check the error object.

 
 
 
PHPRPC for PHP Client
 
 

In Quick start chapter, we have got to know how to use PHPRPC client to access PHPRPC services, let us have a look at a more complicated example:

  1. <?php  
  2. include ("php/phprpc_client.php");  
  3. $client = new PHPRPC_Client();  
  4. $client->setProxy(NULL);  
  5. $client->useService('http://127.0.0.1/server.php');  
  6. $client->setKeyLength(1000);  
  7. $client->setEncryptMode(3);  
  8. $client->setCharset('UTF-8');  
  9. $client->setTimeout(10);  
  10. echo $client->hi('PHPRPC'), "\r\n";  
  11. echo $client->getKeyLength(), "\r\n";  
  12. echo $client->getEncryptMode(), "\r\n";  
  13. echo $client->getCharset(), "\r\n";  
  14. echo $client->getTimeout(), "\r\n";  
  15. ?> 

This is the hi method we used before, maybe you have found out there are no parameters when we initialize PHPRPC_Client, so we need to call useService to indicate a service URL.

setProxy is provided to set HTTP proxy, proxies willn't be used if NULL is set. You can set proxies by two ways:

  1. By URL: http://username:password@host:port, username, password and port are optional
  2. Passing 4 parameters, they are host, port, username and password by order, again, port, username and password are optional.

<span style="color: #008000;">useService</span> is used to set service URL, if it is set when initializing, it is not necessary to call it anymore. But you can change service URL anytime you want by this method .

<span style="color: #008000;">setKeyLength</span> sets key length.

<span style="color: #008000;">setEncryptMode</span> sets encrypted mode.

<span style="color: #008000;">setCharset</span> sets client charset.

<span style="color: #008000;">setTimeout</span> sets timeout period, use the number of seconds as parameter.

<span style="color: #008000;">getKeyLength</span> gets key length, it is a negotiated value you got from the first remote call, otherwise, it is the value you set by setkeyLength (or default value 128).

<span style="color: #008000;">getEncryptMode</span> gets encrypted mode, after the first call, if the server doesn't support encryption, this method will return 0, otherwise return the value you set.

<span style="color: #008000;">getCharset</span> return charset, after the first call, this method will return server side charset, otherwise, it will return the charset you set.

<span style="color: #008000;">getTimeout</span> return timeout period you set or default value 30s.

Reference parameters

When calling PHPRPC service by method names, it is not reference passing, because it is completely different between remote calling and local calling. For local, Reference parameters is actuall passing memory address (pointer), local calling is possible to modify the value of parameters (not modifying pointer). It cost less then passing value. But remote calling will serialize local value, then pass to remote sever, this is passing value, if passing reference is needed, the server side need to serialize parameters, the return to clients. It is costly, that why PHPRPC client don't use reference parameters by default.

It is not difficult to use reference parameters in PHPRPC, but you need invoke to call remote services. Let use see an example. The server published a PHP internal function: sort, below is how we call it from client:

  1. <?php  
  2. include ("php/phprpc_client.php");  
  3. $client = new PHPRPC_Client('http://127.0.0.1/server.php');  
  4. $fruits = array("lemon""orange""banana""apple");  
  5. $args = array(&$fruits, SORT_STRING);  
  6. print_r($fruits);  
  7. $client->invoke('sort'$args, true);  
  8. print_r($fruits);  
  9. ?> 

We will see the result:

Well, success.

Three things need to be aware:

First, the second parameter of invoke is reference parameter, it must be a variable, so we cannot say:

  1. $client->invoke('sort', array(&$fruits, SORT_STRING), true);  

You will get an error like this:

Second, when assigning $args, if $fruits is not a reference, you won't see the changed value after calling invoke by print_r($fruits);, but if you call print_r($args);, you will find out the first element is changed, it successed.

Third, most important one, the third parameter of invoke decide whether use reference parameters, if it is true, then pass reference, if false, pass value. The default value is false, you are able to use invoke to pass value, but it is more complicated, but if you need string type function name to call remote service, it is a good deal for you.

 

 
PHPRPC for PHP utilities

PHPRPC for PHP Date Class

PHP provides many date and time functions, but they can process string or number format only. In PHP, there is no class to present date and time until PHP 5.2, ~Datetime is shipped with PHP 5.2, but there are no detailed documentation of it.

To exchange date type with the other language, PHPRPC use PHPRPC_Date to present date type. When serializing or unserializing, all date class will be processed by PHPRPC_Date, different languages can exchange date type data directly by this class.

Create PHPRPC_Date object

To get a PHPRPC_Date object, 4 ways are available:

  1. PHPRPC_Date construction function
  2. PHPRPC_Date static method now
  3. PHPRPC_Date static method today
  4. PHPRPC_Date static method parse

They are different and relative, when call PHPRPC_Date constructor without parameters, it returns the same result as now. today returns the same date as now, but time part is fulfilled by 0. PHPRPC_Date constructor takes int and string type parameters, parse supports these two types as well. int type parameter is Unix timestamp, constructor and parse accept it identically. For string parameter, it is different, constructor accepts the same formats as strtotime, but parse accepts the following formats:

short format 2008-10-21
long format 2008-10-21 12:13:34
full format 2008-10-21 12:13:34.167

The full format is not supported by strtotime. parse takes PHPRPC_Date object as parameter, it will return the parameter directly.

PHPRPC_Date instance properties

year Year
month Month
day Day
hour Hour
minute Minute
second Second
millisecond Millisecond

PHPRPC_Date instance methods

addMilliseconds($milliseconds) add $milliseconds milliseconds, $milliseconds is integer, positive or negative number
addSeconds($seconds) add $seconds seconds, $seconds is integer, positive or negative number
addMinutes($minutes) add $minutes minutes, $minutes}}} is integer, positive or negative number
addHours($hours) add $hours hours, $hours is integer, positive or negative number
addDays($days) add $days days, $days is integer, positive or negative number
addMonths($months) add $months months, $months is integer, positive or negative number
addYears($years) add $years years, $years is integer, positive or negative number
after($when) If current object is later than $when, return true, otherwise, return false. $when should be accepted by parse
before($when) If current object is earlier than $when, return true, otherwise return false. $when should be accepted by parse
equals($when) If current object equals $when, return true, otherwise, return false. $when should be accepted by parse
set($year, $month, $day[, $hour, $minute, $second[, $millisecond]]) Set values
time() Return Unix timestamp of this object
toString() Return textual representation of current object, it is full format which is supported by parse
dayOfWeek() Return the day of the week, value, from 0-6, 0 is Sunday, 1 is Monday ... 6 is Saturday
dayOfYear() Return the day of the year

PHPRPC_Date static methods

dayOfWeek($year, $month, $day) Return the day of the week, value, from 0-6, 0 is Sunday, 1 is Monday ... 6 is Saturday
dayOfYear($year, $month, $day) Return the day of the year
isLeapYear($year) Return if it is leap year
daysInMonth($year, $month) Return how many days in this month
isValidDate($year, $month, $day) Is it a valid date?
isValidTime($hour, $minute, $second) Is it a valid time?
 
 
 
 
 

Leave a Reply

Your email address will not be published.