Recently I was experimenting with running PHP and the H2 database engine in a Java web server using Caucho Quercus (or just Quercus for short). In theory this would yield an ultra portable platform-independent PHP, web server and database stack. I eventually got it working, but with some limitations. Before I get into details, here are some quick notes: Quercus is a 100% Java implementation of PHP5, though it doesn't support 100% of PHP5's functionality, unfortunately. Also, Quercus' implementation seems to differ from PHP5's implementation sometimes. That said, I thought I would give it a shot anyway, because some popular CMS systems have had success running with Quercus, such as Drupal and Wordpress. I used Jetty as my Java web server (a.k.a. Java web container) and Maven for dependency management. The source code of my experiment is available at github
This tutorial describes how to set up the PHP and database stack in the Jetty web server. First we set up a web application (webapp for short) in Java which can interpret .php files using Quercus. Then we setup the H2 database engine. Last, we setup the part where PHP can connect to H2 while actually thinking it is MySQL that it's connecting to (using H2's MySQL compatibility mode, because PHP does not have support for H2). Here we go!Ultra short walk-through
The long version
- Make sure you have Maven installed.
- Download latest version of Quercus (scroll down, get the WAR file).
- Go to the directory where you downloaded Quercus and install it in your local maven repository by running the Maven command (e.g. for Quercus version 4.0.25):
$ mvn install:install-file -Dfile=quercus-4.0.25.war -DgroupId=com.caucho -DartifactId=quercus -Dversion=4.0.25 -Dpackaging=war
- Checkout git repository:
$ git clone https://github.com/webdevelopersdiary/jamp.git
$ cd jamp
- Run web server:
$ mvn jetty:run
- Wait until you see "[INFO] Started Jetty Server" in the console output and point your browser to http://localhost:8080/
- The document root is located in src/main/webapp/
- Connect to the database in your code using "$pdo = new PDO('mysql:');", mysql_connect() doesn't work due to a driver incompatibility, for more information on this keep on reading.
Setting up Quercus is quite straight-forward. Download the WAR file of the latest version of Quercus (in my case 4.0.25) and install it in your local Maven repository by running this command from the same location as where you downloaded quercus-4.0.25.war:
Then include the following dependency to your Maven project's pom.xml and Quercus should be integrated in your webapp:
The next step is to be able to run the webapp locally, so that's what we use Jetty for. Add this to your pom.xml:
Now Jetty and Quercus should be okay to go. You can verify this by putting a phpinfo.php file with the famous code snippet "<?php phpinfo(); ?>" at src/main/webapp/phpinfo.php (relative to pom.xml's location, create directories if they don't exist) and start up the Jetty webserver:
Wait for Jetty to be completely started (console output should say something like "[INFO] Started Jetty Server") and point your browser to http://localhost:8080/phpinfo.php and verify that Jetty is running and Quercus is installed. (You can stop Jetty by pressing CTRL-C in the console.)
Congratulations! If you made it this far, you have successfully setup a Java web server that can interpret PHP files! But, we're not there yet, we still have to add database support.
We will run the H2 database engine in embedded mode. To do this, we need to include the H2 dependency in the pom.xml. For the integration of H2 and PHP another dependency is required as well: database connection pooling (DBCP), so add both to your pom.xml:
To actually integrate H2 and PHP we need to tell Jetty some additional configuration. Get these two files (web.xml
) and drop them in your src/main/webapp/WEB-INF/ directory (create this directory if it doesn't exist).
At this point, your PHP webapp is entirely configured to connect an in-memory embedded H2 database. But, there is a catch. At the point of writing this article, H2's MySQL compatibility mode is not compatible with Quercus' implementation of the PHP MySQL driver (any attempt to connect to H2 using PHP's mysql_connect() will result in an error complaining about a syntax error in query "SET NAMES ..."). To work around this, we connect to H2 using Quercus' implementation of the PHP PDO driver, which does seem to be compatible with H2's MySQL compatibility mode. So, create a file, e.g. test-database.php and put it in src/main/webapp/test-database.php:
Go to http://localhost:8080/test-database.php to see if it's working (which if everything went okay, it should!).
So now you should have your ultra-portable platform-independent PHP, web server and database stack up and running. Happy experimenting! :-)
I would like to see a working version of Code Igniter using the ActiveRecord class running on this stack. Also, it would be nice to have H2's MySQL compatibility mode compatible with Quercus' MySQL driver, so we can run applications that use mysql_connect() on the stack (e.g. phpMyAdmin).
If you want to call PDOStatement::fetchObject(), you should call PDOStatement::fetchObject('stdClass') instead. This is a bug in Quercus (remember I said in the beginning that sometimes Quercus' implementation differs from PHP's). Acccording to the PHP Manual, the default first argument for PDOStatement::fetchObject should be 'stdClass', it seems the folks at Caucho forgot to implement this.
If you want to use a persistent database file instead of the temporary in-memory database, go to src/main/webapp/WEB-INF/jetty-env.xml and change line
Where you replace 'filename' with a relative path to a file (relative to pom.xml) or an absolute path to a file. Note that "mem:" has an extra ":" after it and "filename" does not. For more information about the H2 JDBC URL see H2's feature list