Quercus Overview and Getting Started Guide
Resin 3.1

Documentation
Examples
Changes

Overview
Installation
Configuration
Quercus
SOA/IoC
JSP
Servlets and Filters
Admin (JMX)
EJB
Amber
Security
Performance
Hessian
XML and XSLT
Third-party
Troubleshooting/FAQ

Overview
Security
Java Integration
Resin Module
Module Status
List of PHP Applications
Troubleshooting/FAQ
Quercus
Quercus
Security

An overview and getting started guide for Quercus.

Introduction

Quercus implements the PHP 5 language in Java, including object and exception support. Quercus is a mixed interpreted/compiled implementation. Long-running PHP scripts are compiled to Java for performance, while short scripts, like eval() scripts are interpreted to avoid compilation overhead.

Because Quercus is a Java implementation, it natively supports 16-bit unicode strings and functions. Quercus (in 3.1.0) supports the new PHP 6 internationalization syntax, and the older unicode conversion functions like iconv. By default, Quercus uses UTF-8 encoding for PHP scripts and runtime unicode conversion.

Running an existing PHP application on Quercus

In general, getting an application to run on Quercus is straightforward. To demonstrate this simple process, let's install WordPress.

Step 1. Create the ${resin.root}/webapps/wordpress directory. That will be the base directory for the wordpress installation. It will correspond to a url like http://localhost:8080/wordpress/. Extract the wordpress files in that directory.

Step 2. Create the ${resin.root}/webapps/wordpress/WEB-INF directory, and add the resin-web.xml file below into that directory. The resin-web.xml file configures QuercusServlet, the Java servlet that interfaces to Quercus, to parse .php files. Since WordPress uses special ISO-8859-1 characters in their PHP scripts, the script encoding is changed from the default UTF-8 to ISO-8859-1. If you need to set ini values, see php.ini.

/C:/resin-3.1.3/webapps/wordpress/WEB-INF/resin-web.xml
<web-app xmlns="http://caucho.com/ns/resin">
  <servlet-mapping Curl-pattern="*.php"
                   servlet-class="com.caucho.quercus.servlet.QuercusServlet">
    <init>
      <script-encoding>iso-8859-1</script-encoding>
    </init>
  </servlet-mapping>
</web-app>

Step 3. If you have not already done so, download the MySQL Connector/J JDBC driver into ${resin.root}/lib to enable mysql database functions (See Using Databases).

Step 4. The configuration for Resin/Quercus is now complete. Now you'll need to go through the application's installation routine. For Wordpress, go to http://localhost:8080/wordpress/wp-admin/setup-config.php to start the installation.

That's it for Wordpress on Quercus. If you are encountering issues with a certain application, please see Resources for assistance.

For a list of applications running successfully on Quercus, see List of PHP Applications Running on Quercus.

Configuring Quercus

php.ini

Individial PHP initialization values can be set in resin-web.xml. For example, to set the settings for sending mail:

WEB-INF/resin-web.xml
<web-app xmlns="http://caucho.com/ns/resin">
  <servlet-mapping url-pattern="*.php"
                   servlet-class="com.caucho.quercus.servlet.QuercusServlet">
    <init>
      <php-ini>
        <sendmail_from>my_email_address</sendmail_from>
        <smtp_username>my_email_username</smtp_username>
        <smtp_password>my_email_password</smtp_password>
      </php-ini>
    </init>
  </servlet-mapping>
</web-app>

A PHP style ini file can also be specified:

WEB-INF/resin-web.xml
<web-app xmlns="http://caucho.com/ns/resin">
  <servlet-mapping url-pattern="*.php"
                   servlet-class="com.caucho.quercus.servlet.QuercusServlet">
    <init>
      <ini-file>WEB-INF/php.ini</ini-file>
    </init>
  </servlet-mapping>
</web-app>

Character Encoding

Because Quercus is 100% Java, Quercus has native support for Unicode and will, by default, parse PHP scripts in UTF-8. This also means Quercus supports the new PHP 6 Unicode keywords like this Unicode typecast: (unicode)"foo". If a PHP application uses special ISO-8859-X characters (i.e. the copyright symbol, accented characters), Quercus will complain because the byte code of those characters are illegal in UTF-8.

There are three encodings you need to worry about: script-encoding, unicodie.output_encoding, and unicode.runtime_encoding encoding. By default, Quercus uses UTF-8 for all three. Script encoding is for when your scripts are in an encoding other than UTF-8.

Script encoding indicates the encoding that is used in the PHP script source files. If the source code for an application is not encoded in UTF-8, the solution is to tell Quercus to parse PHP scripts using the correct character set (ISO-8859-1 for most applications). For example, to tell Quercus to use ISO-8859-1, add <script-encoding> to the init tag of QuercusServlet:

WEB-INF/resin-web.xml
<web-app xmlns="http://caucho.com/ns/resin">

  <servlet-mapping url-pattern="*.php"
                   servlet-class="com.caucho.quercus.servlet.QuercusServlet">
    <init>
      <script-encoding>iso-8859-1</script-encoding>
    </init>
  </servlet-mapping>

</web-app>

If the PHP application also expects conversion from binary to string using a character encoding that is not utf-8, then the unicode.runtime_encoding is used to specify the encoding. In PHP 6, there are two types of strings, Unicode and binary. A binary string is a string where the data is binary, the encoding is unknown, or the encoding is not Unicode (UTF-16). If you ever use a function that will likely return a binary string, then you probably need to set unicode.runtime_encoding. Quercus may convert your binary string to Unicode and then to your output encoding for output to the browser. If your runtime encoding is wrong, then you would see garbage in your browser.

WEB-INF/resin-web.xml
<web-app xmlns="http://caucho.com/ns/resin">

  <servlet-mapping url-pattern="*.php"
                   servlet-class="com.caucho.quercus.servlet.QuercusServlet">
    <init>
      <script-encoding>iso-8859-1</script-encoding>
      <php-ini>
        <unicode.runtime_encoding>iso-8859-1</unicode.runtime_encoding>
      </php-ini>
    </init>
  </servlet-mapping>

</web-app>

unicode.output_encoding is the charset used to display output to the browser. You can set it in your resin-web.xml:

WEB-INF/resin-web.xml
<web-app xmlns="http://caucho.com/ns/resin">
  <servlet-mapping url-pattern="*.php"
                  servlet-class="com.caucho.quercus.servlet.QuercusServlet">
    <init>
      <script-encoding>iso-8859-1</script-encoding>
      <php-ini>
        <unicode.output_encoding>iso-8859-1</unicode.output_encoding>
        <unicode.runtime_encoding>iso-8859-1</unicode.runtime_encoding>
      </php-ini>
    </init>
  </servlet-mapping>
</web-app>

Compiling PHP Scripts for Increased Performance

Quercus will automatically compile PHP scripts into Java classes for better performance. This is available only in Resin Professional.

The default behaviour in Resin Professional is to execute the PHP script in interpreted mode, and to compile the script in the background. When the compiled version is ready, it is used instead of the interpreted version. To force compilation, use the <compile> tag within the <init> tag:

WEB-INF/resin-web.xml
<web-app xmlns="http://caucho.com/ns/resin">
  <servlet-mapping url-pattern="*.php"
                   servlet-class="com.caucho.quercus.servlet.QuercusServlet">
    <init>
      <compile>true</compile>
    </init>
  </servlet-mapping>
</web-app>

Using Databases

JDBC drivers are required to use databases in Quercus. There are JDBC drivers for MySQL, Oracle, SQLite, and many other database engines. The desired JDBC driver should be downloaded into Resin's ${resin.root}/lib directory. Resin will automatically load jars in the lib directory upon startup.

Database typeURL for downloadTypical jar name
MySQLhttp://dev.mysql.com/downloads/connector/j${resin.root}/lib/mysql-connector-java-3.1.11-bin.jar
PostgreSQLhttp://jdbc.postgresql.org/download.html${resin.root}/lib/postgresql-8.1-407.jdbc3.jar
Oraclehttp://www.oracle.com/technology/software/tech/java/sqlj_jdbc${resin.root}/ojdbc14.jar

The database support in Quercus supports robust database connection pooling since Quercus runs in Resin, a fast Java application server. All PHP database access automatically uses JDBC-pooled connections. PHP code does not need changing to take advantage of this capability.

The PHP database apis supported include PDO (portable database objects), mysql, mysql improved, postgres and oracle. Any JDBC-compliant database is available to PHP scripts using PDO.

PDO access to JNDI-configured databases
<php

$db = new PDO("java:comp/env/jdbc/my-database");

...
?>

JNDI DataSource

If a database with JNDI name jdbc/myDatabase is defined in resin.conf, (see Database Configuration), Quercus can do a JNDI lookup for the database when database functions are called. Thus, database connection parameters like user name can be omitted within PHP scripts. This allows easier maintenance and enables Java and PHP database settings to be centrally located in resin.conf.

Scripts can use the jndi name directly:

<?php

  // standard PHP
  //mysql_connect($host, $username, $password, $dbname);

  // using JNDI lookup
  mysql_connect("java:comp/env/jdbc/myDatabaseName");

?>

Or a <database configuration can be provided to QuercusServlet, which cases that DataSource to be used for all database connections regardless of what the script provides in it's connect function call:

WEB-INF/resin-web.xml
<web-app xmlns="http://caucho.com/ns/resin">
  <servlet-mapping url-pattern="*.php"
                   servlet-class="com.caucho.quercus.servlet.QuercusServlet">
    <init>
      <database>java:comp/env/jdbc/myDatabaseName</compile>
    </init>
  </servlet-mapping>
</web-app>

Adding PHP functions by creating a Quercus module

The core PHP functions are implemented inside Quercus modules. Quercus modules are the Java equivalent of PHP modules.

All Quercus modules need to implement AbstractQuercusModule. Functions defined in your modules are callable from within PHP script by using just the function name. Function names need to be distinct in order to prevent name collisions, though Quercus does support function overloading (for Java functions only).

A typical Quercus module looks like:

WEB-INF/classes/example/HelloModule.java
package example;

import com.caucho.quercus.env.Env;
import com.caucho.quercus.module.AbstractQuercusModule;

public class HelloModule extends AbstractQuercusModule
{
  /**
   * @param env provides Quercus environment resources.
   * @param str
   */
  public void HeLLo_TeST(Env env, String str)
  {
    // 'echos' the string
    env.println("hello " + str);
  }
}
example.php
<?php

  // PHP 5 is case-insensitive
  // just prints "hello me" to the browser.
  hello_test("me");

?>

For a tutorial on how to implement your own Quercus module, see the Quercus module tutorial.

Using Plain Old Java Objects (POJO) in PHP Scripts

You do not need to create a Quercus module in order to use your Java code in a PHP script. Quercus provides the java() function to call constructors of Java objects and java_class() to obtain the Java class without calling the constructor. Quercus also extends the PHP language with an import statement.

For more information see Java Integration.

example.php
<?php

  // Quercus specific import statement
  import java.util.Date;

  $date = new Date(123456789);

  $list = java("java.util.ArrayList");

?>

Java Function Arguments/Return Marshaling

Quercus does marshaling to and from PHP values and Java objects. If a Java function requires a String, Quercus will automatically convert the internal Quercus StringValue to a String. If a Java function returns an int, Quercus will create a Quercus LongValue for it.

For other Java Objects like java.util.Data that are returned to PHP, Quercus puts them into wrappers to expose their public methods and members to the PHP script. Java Collection, List, and Map instances have the additional ability to be used within a PHP script like any other PHP array.

For more information, see Java Integration.

Quercus specific functions

Quercus has several Quercus specific PHP functions for debugging and Java integration (JNDI, JMS, and JMX). For more information, see Resin PHP Functions.

Debugging Functions

resin_var_dump($a)
dumps the argument to standard out
resin_call_stack()
returns an array containing the PHP function call stack.
resin_debug($a)
logs the argument into Resin's log at the INFO level
resin_thread_dump()
dumps the Java stack to standard out

JNDI

jndi_lookup() is a Quercus specific function that can be called to retrieve JNDI objects. It is useful in a SOA (Service Oriented Architecture) system to locate a Java service.

Differences from PHP 6

Quercus implements PHP 5 but supports most of PHP 6 language features that are available in the PHP 6 preview distribution. Differences from PHP 6 are:

  1. Unicode support cannot be turned off.
  2. For performance considerations, Unicode string indexing is done by Unicode code units. A Unicode code unit is equivalent to a Java char primitive. In PHP 6, it is done by code points. A code point consists of 1 or 2 code units. Quercus uses code units because determining code point boundaries takes a lot of resources.

Module highlights

Standard modules

Quercus implements the standard PHP libraries (arrays, strings, date, regexp, etc). It also supports extension libraries like zip and zlib for compression, mcrypt for encryption, mail (implemented with JavaMail), and bcmath for large numbers.

APC (object caching)

For PHP object caching, Quercus implements the APC module. PHP applications can use the APC functions to save PHP objects without resorting to serialization and database persistence. Because Quercus runs in Resin, a Java web server, the saved objects are quickly available to any thread running PHP. In other words, unlike Apache which makes sharing across different PHP processes difficult, Quercus can just store a singleton cache of the APC-cached objects.

Because Quercus compiles PHP to Java code, PHP scripts get the opcode caching of APC for free. At this time, performance of Quercus is roughtly comparable with performance of mod_php with APC, i.e. it is significantly faster (3-5 times) than mod_php running by itself.

Image support ('gd')

Quercus provides the image module, so users can use image manipulation functions like watermarking and thumbnail generation in any PHP script on Quercus. .jpg, .png, and .gif files are currently supported. Java users will also find these libraries convenient.

PDF generation (PDFlib api)

PDF generation in Quercus follows the PDFlib API. Since the Quercus PDF implementation is a new implementation in Java, no special downloads are needed to use PDF.

AJAX (JSON)

Quercus also includes the JSON module for encoding and decoding AJAX-style requests. The JSON modules is an excellent example of the benefits of writing modules in Java. Because Java supports garbage collection and protects from pointer overruns, the JSON module implementation is straightforward and reliable, without having to worry about all the possible memory problem in a C library.

Gettext (localization)

Quercus supports the gettext API and .po and .mo files. gettext is a portable API for localization, i.e. translation of program messages. In the future, the Quercus gettext implementation will support Java message bundles so Java applications using PHP can use standard Java localization techniques.

Resources


Quercus
Quercus
Security
Copyright © 1998-2006 Caucho Technology, Inc. All rights reserved.
Resin ® is a registered trademark, and Quercustm, Ambertm, and Hessiantm are trademarks of Caucho Technology.