I love the power of Java and of backend products like OpenJMS, Hibernate, Spring, JMX and so on. And I love the simple, immediate and effective approach of PHP when developing the web presentation layer. I always use both languages together, usually exposing Java services to the PHP applications thru Soap or Xml-Rpc. But how nice would it be to instantiate Java objects directly and transparently inside a php script?
During the last years I've tried a number of times to use the Java extension released with PHP, but for different reasons I've never been fully satisfied with it. Recently I've discovered Quercus, a 100% Java implementation of PHP integrated into Resin, the deservedly well known open source application server from Caucho. It's immediately been a very productive experience and I've already moved some of my PHP applications to Resin/Quercus quite smoothly. Here I would like to explain step by step how to set up an environment as similar as possible to the original native PHP one.
How to I take for granted that you already have a proper JDK installed. Now you can download the open source version of Resin from Caucho and uncompress it. From now on I'll refer to resin's main directory as '%RESIN%' for convenience. The directories bin,conf and webapps will contain what expected.
Resin comes with a default web application, located in webapps/ROOT. We're going to use it for simplicity. PHP files in resin are handled by QuercusServlet, so we need to instruct resin. Let's create a file web.xml under webapps/ROOT/WEB-INF with the following content:
<web-app xmlns="http://caucho.com/ns/resin"> <servlet-mapping url-pattern="*.php" servlet-class="com.caucho.quercus.servlet.QuercusServlet"> <init> <compile>false</compile> </init> </servlet-mapping> </web-app>
This is all you need to run simple php scripts. Start/restart Resin, put in webapps/ROOT/ a, for instance, test.php with:
and on your browser point to http://127.0.0.1:8080/test.php to see the result of phpinfo(). Ok, this is quite simple, but not a "real world" example. When working on php web applications, I usually have at least the following directory structure: - site which is the one publicly accessible(the document root)
- php which contains accessory classes and libraries
(I'm ignoring logs, templates etc. for now) and usually have a prepend.php file that runs before each script and is usually located in my php directory with my libraries. My site directory under resin is the document root (in this case webapps/ROOT/), so I don't have to deal with it, but I need to set include_path and auto_prepend, normally defined in php.ini(or .htaccess) under Apache. Here we don't have php.ini, but we can put them in web.xml. Our new web.xml will be:
<web-app xmlns="http://caucho.com/ns/resin"> <servlet-mapping url-pattern="*.php" servlet-class="com.caucho.quercus.servlet.QuercusServlet"> <init> <compile>false</compile> <php-ini include_path=".:%RESIN/webapps/ROOT/WEB-INF/php" auto_prepend_file="prepend.php" /> </init> </servlet-mapping> </web-app>
In this case the search order for an include() or require() will be the current dir first and then webapps/ROOT/WEB-INF/php (to be created). If you use PEAR or other classes, here you'll add their paths. With auto_prepend we set a prepend file (to be created) to be searched in include_path. Now our environment is much more similar to the one we are used with native PHP, but still a fundamental feature is missing: database connectivity. Don't worry, it's again quite simple. First, open %RESIN%/conf/resin.conf and find the database section. A sample pool configuration will be there commented. You should uncomment it and, if your db engine is for example Mysql, edit the configuration to something like this:
<database> <jndi-name>jdbc/mysql</jndi-name> <driver type="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource"> <url>jdbc:mysql://localhost:3306/your_db_name</url> <user>your_username</user> <password>your_password</password> </driver> <prepared-statement-cache-size>8</prepared-statement-cache-size> <max-connections>20</max-connections> <max-idle-time>30s</max-idle-time> </database>
and save. Don't forget to download mysql Connector/J and put the jar under %RESIN%/lib. The last change to do is in our web.xml, add the following line inside the "<init>" section(where is also <php-ini>): <database>jdbc/mysql</database> and save. That's all. Now, provided that you have put the PEAR's path in include_path and that PEAR DB module is installed, you can write a script like this:
<?php require_once 'DB.php'; $dbh = DB::connect('mysql', false); if (PEAR::isError($dbh)) { die($dbh->getMessage()); } $results=& $dbh->query("select * from your_table"); while($results->fetchInto($row, DB_FETCHMODE_ASSOC)){ echo "<pre>"; print_r($row); echo "</pre>"; }
?>
This is only the first half of the picture, as the most interesting part is the integration between Java and PHP, but this is another story......
Hasta la proxima. |