How it works
A PHP front end is contained in, or associated with, a Java back end. The invoked front end uses HTTP/XML to invoke Java procedures/methods of the running back end. Both, the front end and the back end establish a continuation which may be called at any time from the other continuation. For example procedures of the current PHP environment or of any PHP object may be called by Java, as long as the connection is established.
The mechanism can also be used programmatically: the JSR 223 interface can be used to invoke PHP methods within a running PHP server (Apache/IIS, FastCGI, ...) so that Java components can invoke PHP instances and PHP scripts can call Java (e.g. Java, KAWA, JRuby) based applications or transfer control back to the environment where the request came from.
PHP/Java Bridge Web Application
A PHP/Java Bridge implementation is distributed as a standard JEE web application, JavaBridge.war
. It can be deployed to any standard Java servlet engine or Java application server. It is a distributable ZIP archive, containing example PHP scripts, the JavaBridge.jar
Java library, and a MIT-licensed PHP Java class which may be included by PHP scripts.
A PHP Java class is available from the web application's java/
folder, so that PHP scripts can fetch it and establish the connection using a familiar PHP syntax.
The PHP/Java Bridge web application contains the libraries php-servlet.jar
and php-script.jar
. php-servlet.jar
contains two servlets. The first servlet, PhpJavaServlet
, handles requests from remote PHP scripts running in Apache/IIS or from the command line.
The second servlet, PhpCGIServlet
, handles requests from internet clients directly.
The other library, php-script.jar
, can be used to access the described functionality programmatically using the standard Java 1.6 JSR 223 API.
PhpJavaServlet
The PhpJavaServlet
handles requests from PHP clients.
Apache/IIS/console::PHP <--> PhpJavaServlet
It listens for PHP/Java Bridge protocol requests and invokes Java methods or procedures. The following example accesses a local back end:
<?php
require_once("http://localhost:8080/JavaBridge/java/Java.inc");
$System = java("java.lang.System");
echo $System->getProperties();
?>
Another example which uses define
to direct the PHP
front end to a specific HTTPS back end:
<?php
define ("JAVA_HOSTS", "ssl://mySecureHost.com:8443");
define ("JAVA_SERVLET", "/JavaBridge/servlet.phpjavabridge");
require_once("Java.inc");
$System = java("java.lang.System");
echo $System->getProperties();
?>
This setup requires a PHP-enabled HTTP server, such as Apache or IIS, or a console PHP executable as the front-end.
PhpCGIServlet
The PhpCGIServlet
runs PHP scripts within the J2EE/Servlet engine.
internet browser <--> PhpCGIServlet <--> php-cgi <--> PhpJavaServlet
It starts a PHP FastCGI server, if possible and necessary. Requests for PHP scripts are delegated to the FastCGI server. If the PHP code contains Java calls, the PHP/Java Bridge protocol requests are delegated back to the current VM, to an instance of the PhpJavaServlet
.
This setup requires a php-cgi (Fast-)CGI executable in the PATH.
JSR 223 API
The class
ScriptContextDecorator
can be used to customize the JSR 223 API for use in a servlet environment.
The ScriptEngine returned by getEngineByName('php')
is a simple wrapper for requestDispatcher.include(...)
, while the ScriptEngine returned by getEngineByName('php-invocable')
can capture a remote PHP application, invoke PHP procedures or methods and return the result of each invocation to Java. Please see the API documentation for details.
Standalone
A simple HTTP server is built into the JavaBridge.jar
library. It may be started (if necessary) by double-clicking on JavaBridge.jar
or with the command: java -jar JavaBridge.jar
.
It may be used as a HTTP server or to start a simple socket listener during development.
Although the standalone HTTP server can be used as a replacement for a JEE application server (Java.inc can be fetched via require("http://localhost:8080/JavaBridge/java/Java.inc")
as usual) it doesn't support HTTP/1.1, persistent connections, a connection pool or other standard Java EE features. Its use as a replacement for a Java EE application server is therefore not recommended in production environments.
JSR 223 script runner
Java JDK 1.6 and above contain a JSR 223 command line script interpreter called jrunscript
.
The following examples use the Java 1.6 command line script interpreter:
jrunscript -classpath JavaBridge.jar -l php
# enter in one line:
$buf = new java("java.lang.StringBuffer"); for ($i=0; $i<100000; $i++) $buf->append($i); echo $buf->length();
488890
Especially interesting is the for loop, its statements are sent to the Java continuation immediately, w/o generating any round-trips. This is why the bridge executes a PHP/Java mix almost as fast as a native script engine (see the benckmark results from the FAQ for details).
The next example demonstrates how to capture an environment and pass it on to a continuation. This is useful for PHP classes which should implement Java interfaces:
<?php
$vec = new java("java.util.Vector");
function toString() {global $vec; return "ccl::".$vec[0];}
$vec->add(9); $vec->add(java_closure());
echo $vec;
?>
jrunscript -classpath JavaBridge.jar -l php test.php
=>[9, ccl::9]
The above code captures the current PHP environment and passes it on to the Java continuation. When the Java vector is evaluated, it invokes the toString() method of the Java object, which in turn accesses the captured environment. It is programmed so that it returns the first element of the global vector $vec.
PHP/Java integration
The Java.inc
PHP library sets up an autoload handler to import Java into PHP's environment.
The following example autoloads the standard Java classes from Java and makes them available to PHP.
<?php
require_once("http://localhost:8080/JavaBridge/java/Java.inc");
use java\lang\String as JString;
use java\util\ArrayList as JList;
class String extends JString {
function toString () {
return "hello " . parent::toString();
}
}
$str = new String("Java");
$list = new JList();
$list->add (java_closure($str));
$list->add ("from PHP");
$ar = java_values ($list->toArray());
foreach($ar as $entry) echo "$entry<br>\n"
?>
=>hello Java
from PHP
It makes
use of the syntax transformer built into PHP 5.3 and above to
import and extend the functionality of Java classes. In the above example java.lang.String
is
extended by a PHP class, overriding the functionality of its toString()
method. An instance of this
class is then passed to a java.lang.ArrayList
.
The entire list is then converted into a PHP array using java_values
.