<document>
  <header>
    <product>resin</product>
    <title>Quercus: PHP in Java</title>
    <level>toplevel-topic</level>
    <type>contents</type>
    <description>
      <p>
      <em>Quercus</em> is Caucho Technology's fast, open-source, 100%
      Java implementation of the PHP language.  Performance is 4x mod_php
      and is comparable with PHP accelerator performance. Quercus uses
       <a href="resin-ioc.xtp">Resin-IoC/WebBeans</a> to integrate with
      Resin services.
      </p>
    </description>
  </header>

  <body>

<localtoc/>

<s1 title="Introduction to Quercus">

<p>Quercus is Caucho Technology's fast, open-source, 100% Java implementation
of the PHP language.  Quercus is a feature of Caucho Technology's Resin
Application Server and is built into Resin - there is no additional
download/install.  Developers using Resin can launch PHP projects without
having to install the standard PHP interpreter (http://www.php.net) as Quercus
takes on the role of the PHP engine.</p>


<s2 title="What is Quercus">

<p>Quercus implements PHP 5 and is internationalization/localization
(i18n/l10n) aware.  Quercus natively supports Unicode and the new Unicode
syntax of the up-and-coming PHP 6.  Quercus implements a growing list of PHP
extensions (i.e. APC, iconv, GD, gettext, JSON, MySQL, Oracle, PDF, Postgres,
etc.).  Many popular PHP applications will run as well as, if not better, than
the standard PHP interpreter straight out of the box.</p>

<s3 title="Resin with Quercus">

<p>Quercus is much more than just yet another PHP engine.  Quercus is the first
to tightly integrate the web server with a PHP engine.  Quercus runs on top of
Caucho Technology's Resin Application Server.  As a result, PHP applications
can automatically and immediately take advantage of Resin's advanced features
like connection pooling, distributed sessions, load balancing, and proxy
caching.</p>

</s3>

<s3 title="A New Java/PHP Architecture">

<p>Quercus is pioneering a new mixed Java/PHP approach to web applications and
services.  On Quercus, Java and PHP is tightly integrated with each other - PHP
applications can choose to use Java libraries and technologies like JMS, EJB,
SOA frameworks, Hibernate, and Spring.  This revolutionary capability is made
possible because 1) PHP code is interpreted/compiled into Java and
2) Quercus and its libraries are written entirely in Java.
This lets PHP applications and Java libraries to talk directly with one
another at the program level.  To
facilitate this new Java/PHP architecture, Quercus provides an API and interface
to expose Java libraries to PHP.</p>

</s3>

</s2>

<s2 title="Benefits of Quercus">

<p>Quercus and Quercus' PHP libraries are written entirely in Java, thereby
taking the advantages of Java applications and infusing them into PHP.  PHP
applications running on Quercus are simply faster, easier to develop, more
capable, more secure, and more scalable than any other PHP solution.</p>

<p>Quercus gives both Java and PHP developers a fast, safe, and powerful
alternative to the standard PHP intepreter.  Developers ambitious enough to
use PHP in combination with Java will benefit the most from what Quercus has
to offer.</p>

<s3 title="Performance - simply faster">

<ul>
<li>Quercus outperforms straight mod_php by about 4x for MediaWiki and
Drupal.</li>
<li>PHP developers can use Java tools like profilers to get in-depth
information about the PHP program performance.</li>
</ul>

</s3>

<s3 title="Development - fast, safe, and easy">

<ul>
<li>PHP extensions written in Java are fast, safe, and relatively easy to
develop compared to those written in C.  Since Java is the library language,
developers won't need to be paranoid about third-party libraries having
C-memory problems or segvs and are freed to concentrate on solving the
objectives at hand.</li>
</ul>

</s3>

<s3 title="Capability - powerful Java technologies at the developer's fingertips">

<ul>

<li>Quercus has the best of both worlds: PHP and Java.  PHP applications can take advantage of Java technologies like JMS, EJB,
SOA frameworks, Hibernate, and Spring.</li>
</ul>

</s3>

<s3 title="Security - no more pesky C memory bugs">

<ul>
<li>All Quercus extensions libraries are coded in Java.  Therefore, developers
do not have to worry about C pointer overruns and segmentation faults from PHP
extensions anymore.</li>
</ul>

</s3>

<s3 title="Scalability - Massive clusters of PHP">

<ul>
<li>Thanks to Resin, PHP applications can beautifully scale to as many servers
as desired.</li>
<li>PHP applications can now enjoy connection pooling, distributed sessions,
fail-safe load balancing, and proxy caching.  These benefits require no change
in the PHP code.</li>
</ul>

</s3>

<s3 title="Internationalization - 16-bit unicode">

<ul>
<li>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 <code>iconv</code>.  Since 3.1.3, the new PHP6 unicode features
are off by default but they can be enabled with the PHP ini
<code>unicode.semantics=on</code>.</li>
</ul>

</s3>
</s2>

</s1>

<s1 name="existing" title="Existing PHP applications on Quercus">

<s2 title="Killer Apps: Mediawiki, Wordpress">

<p>Caucho has designated a few applications as Quercus "killer apps".
For these applications, we take extra time to test that each new application
version works well with Quercus.  Any issues raised with the killer
apps have priority over other Quercus bugs.</p>

<ul>
<li><a href="http://wiki.caucho.com/Quercus:_Mediawiki">http://wiki.caucho.com/Mediawiki</a></li>
<li><a href="http://wiki.caucho.com/Quercus:_Wordpress">http://wiki.caucho.com/Wordpress</a></li>
</ul>

</s2>

<s2 title="Other applications">

<ul>
<li><a href="http://wiki.caucho.com">http://wiki.caucho.com</a></li>
<li><a href="http://wiki.caucho.com/Quercus:_DokuWiki">DokuWiki</a></li>
<li><a href="http://wiki.caucho.com/Quercus:_Drupal">Drupal</a></li>
<li><a href="http://wiki.caucho.com/Quercus:_Gallery2">Gallery2</a></li>
<li><a href="http://wiki.caucho.com/Quercus:_Mantis">Mantis</a></li>
<li><a href="http://wiki.caucho.com/Quercus:_Mediawiki">Mediawiki</a></li>
<li><a href="http://wiki.caucho.com/Quercus:_Openads">Openads</a></li>
<li><a href="http://wiki.caucho.com/Quercus:_PHP-Nuke">PHP-Nuke</a></li>
<li><a href="http://wiki.caucho.com/Quercus:_phpMyAdmin">phpMyAdmin</a></li>
<li><a href="http://wiki.caucho.com/Quercus:_PHProjekt">PHProjekt</a></li>
<li><a href="http://wiki.caucho.com/Quercus:_Vanilla">Vanilla</a></li>
<li><a href="http://wiki.caucho.com/Quercus:_Wordpress">Wordpress</a></li>
</ul>

</s2>
</s1>

<s1 name="configuring" title="Configuring Quercus">

<s2 title="QuercusServlet">

<p><code>QuercusServlet</code> is the servlet responsible for handling
PHP requests.  It acts like the PHP servlet, taking *.php requests,
parsing and interpreting them.  <code>QuercusServlet</code> has three
modes: interpreted, compiled and automatic.</p>

<ul>
<li>Interpreted mode evaluates PHP based on Quercus's
internal parse tree.  It's a bit slower at runtime, but faster to
startup.</li>
<li>Compiled mode translates PHP into Java and if the fastest PHP mode
available.  Because it calls the Java compiler, it's slower to
startup.</li>
<li>Automatic mode is a mixture.  It will start in interpreted mode
and compile PHP pages in the background.  When the compilation
finishes, Quercus will switch to the compiled class.</li>
</ul>

<deftable title="QuercusServlet init values">
<tr>
  <th>parameter</th>
  <th>description</th>
  <th>default</th>
</tr>
<tr>
  <td>compile</td>
  <td>true, false or lazy</td>
  <td>lazy</td>
</tr>
<tr>
  <td>database</td>
  <td>A JNDI name of a preconfigured database to use for all PHP methods.</td>
  <td></td>
</tr>
<tr>
  <td>strict</td>
  <td>set strict syntax checking</td>
  <td>false</td>
</tr>
<tr>
  <td>php-ini</td>
  <td>A resin-xml configuration of php.ini values.  Each php.ini is
  an attribute to the &lt;php-ini&lt; element.</td>
  <td></td>
</tr>
<tr>
  <td>ini-file</td>
  <td>A path to a traditional php.ini file</td>
  <td></td>
</tr>  
</deftable>

<p>Quercus can also be configured using traditional init-param servlet
values.</p>

<deftable title="QuercusServlet init-param">
<tr>
  <th>parameter</th>
  <th>description</th>
  <th>default</th>
</tr>
<tr>
  <td>compile</td>
  <td>sets the compile mode: true, false, lazy</td>
  <td>lazy</td>
</tr>
<tr>
  <td>database</td>
  <td>sets a JNDI database to be used for all PHP database
  access.</td>
  <td></td>
</tr>
<tr>
  <td>ini-file</td>
  <td>set a path to a php.ini file</td>
  <td></td>
</tr>  
<tr>
  <td>strict</td>
  <td>sets strict-mode compile checking</td>
  <td>false</td>
</tr>  
</deftable>


</s2>

<s2 name="php.ini" title="php.ini">

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

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

<p>A PHP style ini file can also be specified:</p>

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

</s2>

<s2 name="encoding" title="Character Encoding">

<p>Quercus 3.1.0 supports PHP6 and has full support for Unicode.  But like PHP6, Quercus 3.1.3 has its
Unicode support turned off by default for compatibility with legacy PHP applications.
Unicode support can be enabled with the php ini <code>unicode.semantics</code>.</p>

<p>With unicode semantics off, Quercus will intrepret bytes in the default ISO-8859-1 encoding.
Quercus will behave just as PHP5 would. With it on, PHP5 applications may break and
you need to be concerned with the following three encodings options:
script-encoding, unicode.output_encoding, and unicode.runtime_encoding.  By default,
Quercus uses UTF-8 for all three.</p>

<p>
Script encoding indicates the encoding of PHP script source files.
If the source code for an application is not encoded in UTF-8, Quercus may give invalid UTF-8
conversions errors when it tries to convert bytes read to 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 <code>&lt;script-encoding></code> to the <code>init</code> tag
of QuercusServlet:</p>

<example title="WEB-INF/resin-web.xml">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;servlet-mapping url-pattern="*.php"
                   servlet-class="com.caucho.quercus.servlet.QuercusServlet"&gt;
    &lt;init&gt;
      <b>&lt;script-encoding&gt;ISO-8859-1&lt;/script-encoding&gt;</b>
    &lt;/init&gt;
  &lt;/servlet-mapping&gt;

&lt;/web-app>
</example>

<p>
If the PHP application also expects conversion from binary to string using a
character encoding that is not UTF-8, then the
<code>unicode.runtime_encoding</code> 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.</p>

<example title="WEB-INF/resin-web.xml">
&lt;web-app xmlns="http://caucho.com/ns/resin">

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

&lt;/web-app>
</example>

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

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

</s2>

<s2 name="compiling" title="Compiling PHP Scripts for Increased Performance">

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

<p>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 <code>&lt;compile></code> tag within the
<code>&lt;init></code> tag:</p>

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

</s2>

<s2 name="databases" title="Using Databases">

<p>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 <code>${resin.root}/lib</code>
directory.  Resin will automatically load jars in the <code>lib</code>
directory upon startup.</p>

<deftable>
<tr>
  <th>Database type</th>
  <th>URL for download</th>
</tr>
<tr>
  <td>MySQL</td>
  <td><a href="http://dev.mysql.com/downloads/connector/j">http://dev.mysql.com/downloads/connector/j</a></td>
</tr>
<tr>
  <td>PostgreSQL</td>
  <td><a href="http://jdbc.postgresql.org/download.html">http://jdbc.postgresql.org/download.html</a></td>
</tr>
<tr>
  <td>Oracle</td>
  <td><a href="http://www.oracle.com/technology/software/tech/java/sqlj_jdbc">http://www.oracle.com/technology/software/tech/java/sqlj_jdbc</a></td>
</tr>

</deftable>

<p>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.</p>

<p>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.</p>

<example title="PDO access to JNDI-configured databases">
&lt;php

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

...
?>
</example>

<s3 name="datasource" title="JNDI DataSource">

<p>If a database with JNDI name <code>jdbc/myDatabase</code> is defined in
resin.xml, (see <a href="config-database.xtp">Database Configuration</a>),
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.xml.</p>

<p>Scripts can use the jndi name directly:</p>

<example>
&lt;?php

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

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

?>
</example>

<p>
You can use a JNDI <code>&lt;database</code> configuration in the
WEB-INF/resin-web.xml to override the PHP connection code.  If a &lt;database>
is provided, any <code>mysql_connect</code> call will return
the configured database,
ignoring the parameters to the <code>mysql_connect</code> call.
</p>

<example title="Example: overriding database configuration in resin-web.xml">
&lt;web-app xmlns="http://caucho.com/ns/resin">
  &lt;database jndi-name="jdbc/mysql">
    &lt;driver type="org.gjt.mm.mysql.Driver">
      &lt;url>jdbc:mysql://localhost:3306/test&lt;/url>
      &lt;user>&lt;/user>
      &lt;password>&lt;/password>
    &lt;/driver>
  &lt;/database>

  &lt;servlet-mapping url-pattern="*.php"
                   servlet-class="com.caucho.quercus.servlet.QuercusServlet">
    &lt;init>
      <b>&lt;database>java:comp/env/jdbc/myDatabaseName&lt;/database></b>
    &lt;/init>
  &lt;/servlet-mapping>
&lt;/web-app>
</example>

</s3>

<s3 title="database-default and spy">

<p>Resin has a handy <a
href="env-tags.xtp#database-default">&lt;database-default></a>
configuration tag that lets you set connection pooling an database
defaults for all database connections.  Since Quercus can create
pools automatically, &lt;database-default> gives you control over
those pools.</p>

<p>In particular, the &lt;spy> tag shows the queries that your PHP
script is sending to the database at log level "fine" for
"com.caucho.sql.spy".</p>

<example title="Example: database-default for spy">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;log-handler name="com.caucho.sql.spy" path="WEB-INF/spy.log"/>
  &lt;logger name="com.caucho.sql.spy" level="fine"/>
  
  &lt;database-default>
    &lt;spy/>
  &lt;/database-default>

&lt;/web-app>
</example>

</s3>

</s2>
</s1> <!-- configuration -->

<s1 title="Java/PHP integration">

<s2 title="Using Java services from PHP: Resin-IoC/WebBeans">

<p>If you're already using <a href="resin-ioc.xtp">Resin-IoC/WebBeans</a>
to organize your application into services, your PHP script can grab
a reference to the service with the registered name.  Calling
<code>java_bean</code> with a singleton bean's name will return
the singleton, and calling <code>java_bean</code> with a component's
name will return a new instance of the component.  Quercus will automatically
marshal PHP calls to the bean's Java methods, so your service's entire
functionality will be available to the PHP script.</p>

<example title="Example: using a WebBeans service">
&lt;?php

  $house_manager = java_bean("houseManager");

  $house = $house_manager->findHouse("Gryffindor");

  foreach ($house->getPrefects() as $prefect) {
    echo $prefect . "\n";
  }

?>
</example>

<p>WebBeans (JSR-299) is an inversion-of-control/dependency-injection
framework specification for JavaEE 6 which is designed to organize
Java services, and also integrate with scripting frameworks.  WebBeans
integrates tightly with the newest EJB and persistence specifications,
so PHP applications using the WebBeans interface will gain the latest,
cleanest integration with Java applications.
<a href="resin-ioc.xtp">Resin-IoC</a> is Caucho's implementation of
the WebBeans framework, and serves as the underlying architecture of Resin
itself, as well as the <a href="resin-ejb.xtp">Resin EJB</a>
implementation.</p>

</s2>

<s2 title="Working with Java classes in PHP">

<s3 title="Instantiating objects by class name">
<p>An alternative to <code>import</code> is to use 
<code>new Java(...)</code> with the class name and any
constructor arguments.</p>

<example>
&lt;?php

  $a = new Java("java.util.Date", 123);

  echo $a->time;

?>
</example>

</s3>

<s3 title="Importing classes">
<p>
Quercus supports the use of an import statement in PHP.  <code>import</code>
makes any java class available to the PHP script with it's unqualified name.
</p>

<example title="Example: creating a Java class with import">
&lt;?php

  import java.util.Date;

  $a = new Date(123);

  echo $a->time;
?>
</example>

<p>
User classes can be placed in the webapp's WEB-INF/classes directory.
</p>

<example title="Example: WEB-INF/classes/example/MyBean.java">
package example;

public class MyBean
{
  int _value;

  public MyBean(int value)
  {
    _value = value;
  }

  public int getValue()
  {
    return _value;
  }

  public String makeMessage()
  {
    return "Hello, my value is " + _value;
  }
}
</example>

<example title="mybean.php">
&lt;?php

  import example.MyBean;

  $bean = new MyBean(123);

  var_dump($bean);
  var_dump($bean->value);
  var_dump($bean->makeMessage());
?>
</example>

<p>The <code>import</code> keyword will also work on PHP classes but it has a
different functionality than for Java classes.  <code>import</code> will try to
autoload PHP classes by including  the file WEB-INF/classes/<i>classname</i>.php
from the application's WEB-INF/classes directory.</p>

</s3>
</s2>

<s2 title="Calling Java Methods">

<p>
PHP syntax is used for invoking methods.
PHP property syntax can be used for invoking getters and setters of Java objects.
</p>

<example>
&lt;?php

  import java.util.Date;

  $a = new Date(123);

  echo $a->getTime();    # calls getTime()
  echo $a->setTime(456); # calls setTime(456)

  echo $a->time;      # calls getTime()
  $a->time = 456;     # calls setTime(456)
?>
</example>

<s3 title="Static members and methods">

<p>Static methods and members are available using PHP syntax if the Java class has been imported.</p>

<example>
&lt;?php

import java.util.Calendar;

$calendar = Calendar::getInstance();

var_dump($calendar);
?>

</example>

<p>An alternative to <code>import</code> is to use <code>java_class()</code> to access static members and methods.</p>

<example>
&lt;?php

  $class = java_class("java.lang.System");

  # System.in
  $in = $class->in;
  
  # System.currentTimeMillis();
  $time = $class->currentTimeMillis();

?>
</example>

</s3>

<s3 title="Java method overloading">

<p>Quercus allows overloaded Java methods to be called from within PHP code.
The number of arguments is most important, followed by the argument
types.  Quercus will use the method whose arguments are the most easily
marshaled (i.e. a PHP string easily goes into a Java String whereas a
PHP array is a mismatch for a Java int).</p>

<p>Because the PHP language itself does not support overloading, the
Quercus overloading of Java methods may not be exact.  Therefore, it's
best to keep overloading to a minimum.  Overloading by the number of
arguments will always work, but overloading by types is trickier.</p>


<example title="Example: MyModule.java">
import com.caucho.quercus.module.AbstractQuercusModule;

public class MyModule extends AbstractQuercusModule
{
  public static void foo(String a, boolean b)
  {
  }

  public static void foo(String a, String b)
  {
  }
}
</example>

<example title="example.php">
&lt;?php

  foo('abc', false);

?>
</example>

<p>In the example above, the first Java method <code>public static void foo(String a, boolean b)</code> is called because it requires the least amount of type coercion.</p>

<note>Only Java methods with the same amount of arguments will be considered.</note>

</s3>

</s2>

<s2 name="module" title="Modules: Adding PHP functions">

<p>The core PHP functions are implemented inside Quercus modules.  Quercus modules are the Java equivalent of PHP modules.  </p>

<p>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).</p>

<p>A typical Quercus module looks like:</p>

<example title="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>

<example title="example.php">
&lt;?php

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

?>
</example>

<p>For a tutorial on how to implement your own Quercus module, see the <a href="../examples/quercus-module/index.xtp">Quercus module tutorial</a>.</p>

</s2>

<s2 title="Marshalling: PHP to Java conversions">

<s3 title="PHP types">
<p>For every PHP type, there is a Java type that is used
internally to represent the corresponding PHP value. All of the Java types extend
<code>Value</code>.</p>

<deftable>
<tr>
  <th>PHP type</th>
  <th>Quercus class</th>
</tr>
<tr>
  <td>null</td>
  <td>NullValue</td>
</tr>
<tr>
  <td>string (php5)</td>
  <td>StringBuilderValue</td>
</tr>
<tr>
  <td>string (php6, binary)</td>
  <td>BinaryBuilderValue</td>
</tr>
<tr>
  <td>string (php6, unicode)</td>
  <td>UnicodeBuilderValue</td>
</tr>
<tr>
  <td>bool</td>
  <td>BooleanValue</td>
</tr>
<tr>
  <td>int</td>
  <td>LongValue</td>
</tr>
<tr>
  <td>float</td>
  <td>DoubleValue</td>
</tr>
<tr>
  <td>array</td>
  <td>ArrayValue</td>
</tr>
<tr>
  <td>object</td>
  <td>ObjectValue</td>
</tr>
<tr>
  <td>ref/var</td>
  <td>Var</td>
</tr>
</deftable>

</s3>

<s3 title="Java method arguments">

<p>In Quercus, Java methods can be called from within PHP.  Java arguments for
Java methods are marshaled to the correct type from the PHP parameters
that were passed in.</p>

<p>When the Java argument type is declared to be Object, the value will
be marshaled to a Java object.  For example, a PHP int (LongValue) will be
marshaled to an Integer.  The only exceptions are PHP arrays and objects: they
are passed in as-is without marshaling.</p>

<p>When the Java argument type is declared to be a Quercus Value, the PHP value
is passed in directly without marshaling.</p>

<p>If the Java argument type is an object, passing in a PHP <code>NULL</code> will
result in a null Java argument.</p>

<deftable title="Java to PHP conversion">
<tr>
  <th width="50%">Java Type</th>
  <th>PHP Type</th>
  <th>Quercus Type</th>
</tr>
<tr>
  <td>null</td>
  <td>NULL</td>
  <td>NullValue</td>
</tr>
<tr>
  <td>boolean</td>
  <td>bool</td>
  <td>BooleanValue</td>
</tr>
<tr>
  <td>Boolean</td>
  <td>bool</td>
  <td>BooleanValue</td>
</tr>
<tr>
  <td>byte</td>
  <td>int</td>
  <td>LongValue</td>
</tr>
<tr>
  <td>Byte</td>
  <td>int</td>
  <td>LongValue</td>
</tr>
<tr>
  <td>short</td>
  <td>int</td>
  <td>LongValue</td>
</tr>
<tr>
  <td>Short</td>
  <td>int</td>
  <td>LongValue</td>
</tr>
<tr>
  <td>int</td>
  <td>int</td>
  <td>LongValue</td>
</tr>
<tr>
  <td>Integer</td>
  <td>int</td>
  <td>LongValue</td>
</tr>
<tr>
  <td>long</td>
  <td>int</td>
  <td>LongValue</td>
</tr>
<tr>
  <td>Long</td>
  <td>int</td>
  <td>LongValue</td>
</tr>
<tr>
  <td>float</td>
  <td>float</td>
  <td>DoubleValue</td>
</tr>
<tr>
  <td>Float</td>
  <td>float</td>
  <td>DoubleValue</td>
</tr>
<tr>
  <td>double</td>
  <td>float</td>
  <td>DoubleValue</td>
</tr>
<tr>
  <td>Double</td>
  <td>float</td>
  <td>DoubleValue</td>
</tr>
<tr>
  <td>String</td>
  <td>string (php5)</td>
  <td>StringBuilderValue</td>
</tr>
<tr>
  <td>String</td>
  <td>unicode (php6)</td>
  <td>UnicodeBuilderValue</td>
</tr>
<tr>
  <td>char</td>
  <td>string (php5)</td>
  <td>StringBuilderValue</td>
</tr>
<tr>
  <td>char</td>
  <td>unicode (php6)</td>
  <td>UnicodeBuilderValue</td>
</tr>
<tr>
  <td>Character</td>
  <td>string (php5)</td>
  <td>StringBuilderValue</td>
</tr>
<tr>
  <td>Character</td>
  <td>unicode (php6)</td>
  <td>UnicodeBuilderValue</td>
</tr>
<tr>
  <td>char[]</td>
  <td>string (php5)</td>
  <td>StringBuilderValue</td>
</tr>
<tr>
  <td>char[]</td>
  <td>unicode (php6)</td>
  <td>UnicodeBuilderValue</td>
</tr>
<tr>
  <td>byte[]</td>
  <td>string (php5)</td>
  <td>StringBuilderValue</td>
</tr>
<tr>
  <td>byte[]</td>
  <td>string (php6)</td>
  <td>BinaryBuilderValue</td>
</tr>
<tr>
  <td>Object[] (any other array)</td>
  <td>array</td>
  <td>ArrayValue</td>
</tr>
<tr>
  <td>Calendar</td>
  <td>effectively int (getTimeInMillis())</td>
  <td>JavaValue</td>
</tr>
<tr>
  <td>Date</td>
  <td>effectively int (getTime())</td>
  <td>JavaValue</td>
</tr>
<tr>
  <td>URL</td>
  <td>effectively string (toString())</td>
  <td>JavaValue</td>
</tr>
<tr>
  <td>Collection</td>
  <td>array</td>
  <td>JavaValue</td>
</tr>
<tr>
  <td>List</td>
  <td>array</td>
  <td>JavaValue</td>
</tr>
<tr>
  <td>Map</td>
  <td>array</td>
  <td>JavaValue</td>
</tr>
<tr>
  <td>other Java Objects</td>
  <td>object</td>
  <td>JavaValue</td>
</tr>
<tr>
  <td>Value</td>
  <td>any</td>
  <td>Value</td>
</tr>
</deftable>

<p>Java objects like Calendar and Map are placed inside JavaValues and then
returned to the PHP environment.  A JavaValue is a wrapper that exposes
the object's Java methods to PHP.  For example, if <code>$url</code> is holding
a Java URL object, then we can use <code>$url->getHost()</code> to call the
URL's <code>getHost()</code> method.</p>

<p>Some Java objects may have an effective PHP value.  Take for instance, Date.
A Date object is, for practical purposes, a PHP int with it's value pegged to
Date.getTime().</p>

<p>Collection, List, and Map behave just like PHP arrays.  Suppose
<code>$map</code> holds a Java HashMap, then it's certainly valid to do
<code>$map["foo"] = "bar"</code>.  However, there are some limitations that
are dependent on the underlying Java type.  For example,
<code>$list[-1] = 5</code> will not be possible for a Java List because List
indexes start at 0.</p>

</s3>
</s2> <!-- marshal -->

<s2 title="HttpServletRequest and HttpSession">

<p>
You may retreive the <a href="javadoc|javax.servlet.http.HttpServletRequest"/>
object by calling <code>quercus_servlet_request()</code> from within your
PHP script.
</p>

<p>
PHP sessions are not shared with servlet sessions.  The <code>HttpServletRequest</code>
object can be used to obtain the servlet session if required.
</p>

<example title="$request->getSession(true) HttpSession">
&lt;?php
  $request = quercus_servlet_request();

  $session = $request->getSession(true);

  $foo = $session->getAttribute("foo");
?>
</example>

</s2>

<s2 title="Using META-INF/services to package Quercus extensions in jar files">

<p>
At startup time Quercus discovers and uses files within the META-INF/services
to discover modules and classes that are made available within the PHP
environment.
</p>

<s3 title="META-INF/services/com.caucho.quercus.QuercusModule">

<p>
<code>META-INF/services/com.caucho.quercus.QuercusModule</code>
contains a list of classes that are modules.  Each public member of a
module becomes available as a top-level PHP function.
</p>

<p>
For example a line like:
</p>

<example title="META-INF/services/com.caucho.quercus.QuercusModule">
...
com.caucho.quercus.lib.date.DateModule
...
</example>

<p>
references the java class:
</p>

<example title="com/caucho/quercus/lib/date/DateModule.java">
package com.caucho.quercus.lib.date.DateModule

public class DateModule
  extends AbstractQuercusModule
{
  ...

  public static final int CAL_GREGORIAN = 0;

  ...

   public static int cal_days_in_month(int cal, int month, int year)
   {
     ...
   }

   ...
}
</example>

<p>
When Quercus starts, the DateModule class is automatically
introspected, and a PHP script can call the function defined in the
module:
</p>

<example title="Calling the cal_days_in_month function">
&lt;?php
$var = cal_days_in_month(CAL_GREGORIAN, 2, 2000)
?>
</example>

</s3>

<s3 title="META-INF/services/com.caucho.quercus.QuercusClass">

<p>
<code>META-INF/services/com.caucho.quercus.QuercusClass</code>
contains a list of classes that should become available to PHP as
objects.
</p>

<p>
For example a line like:
</p>

<example title="META-INF/services/com.caucho.quercus.QuercuClass">
...
com.caucho.quercus.lib.date.DateTime
...
</example>

<p>
references the java class:
</p>

<example title="com/caucho/quercus/lib/date/DateTime.java">
package com.caucho.quercus.lib.date;

public class DateTime
{
  public static final String ISO8601 = "Y-m-d\\TH:i:sO";

  public DateTime(String timeString)
  {
    ...
  }

  ...

  public String format(String format)
  {
    ...
  }
 
   ...
}
</example>

<p>
When Quercus starts, the DateTime class is automatically
introspected, and a PHP script can instantiate and use the object:
</p>

<example title="Using the DateTime class in PHP">
&lt;?php
$var = new DateTime("last week");

echo $a->format(DateTime::ISO8601);
?>
</example>

</s3>

</s2>


</s1> <!-- java integration -->

<s1 name="module_highlights" title="PHP Module highlights">
<s2 name="standard_modules" title="Standard modules">

<p>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.</p>

</s2>

<s2 name="apc_module" title="APC (object caching)">

<p>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.</p>

<p>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.</p>

</s2>

<s2 name="gd_module" title="Image support ('gd')">

<p>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.</p>

</s2>

<s2 name="pdflib_module" title="PDF generation (PDFlib api)">

<p>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.</p>

</s2>

<s2 name="json_module" title="AJAX (JSON)">

<p>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.</p>

</s2>

<s2 name="gettext_module" title="Gettext (localization)">

<p>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.</p>

</s2>
</s1> <!-- module highlights -->

<s1 title="ResinModule">
<s2 title="jndi_lookup">

<p>Retrives an object from JNDI.  jndi_lookup is useful in a
<a href="soa.xtp">SOA (Service Oriented Architecture)</a>
system to locate a Java service.
</p>

<example>
&lt;?php

$conn = jndi_lookup("java:comp/env/jms/jms-connection-factory");
$queue = jndi_lookup("java:comp/env/jms/test-queue");

...
?>
</example>

</s2>

<s2 title="mbean_explode">

<p>Explodes a JMX ObjectName into an array.</p>

<example title="mbean_explode">
&lt;?php

var_dump(mbean_explode("resin:type=WebApp,name=/foo,Host=bar.com"));

?>
</example>
<results>
array(4) {
  [":domain:"]=>
  string(5) "resin"
  ["Host"]=>
  string(7) "bar.com"
  ["name"]=>
  string(4) "/foo"
  ["type"]=>
  string(6) "WebApp"
}
</results>

</s2>

<s2 title="mbean_implode">

<p>Creates a JMX ObjectName from an array.</p>

<example title="mbean_implode">
&lt;?php

$a = array(":domain:"=>"resin", "type" => "ThreadPool");

var_dump(mbean_implode($a));

?>
</example>
<results>
resin:type=ThreadPool
</results>

</s2>

<s2 title="MBeanServer">

<p>An object representing a JMX MBeanServer.</p>

<example>
&lt;?php

$mbeanServer = new MBeanServer();

$threadPool = $mbeanServer->lookup("resin:type=ThreadPool");

echo "thread-max: " . $threadPool->threadMax;
</example>

<s3 title="lookup">

<p>Returns a proxy to the mbean matching the given name.</p>

<example>
&lt;?php

$mbeanServer = new MBeanServer();

$threadPool = $mbeanServer->lookup("resin:type=ThreadPool");
</example>

</s3>

<s3 title="query">

<p>Returns mbean proxies matching the name pattern.</p>

<example>
&lt;?php

$mbeanServer = new MBeanServer();

foreach ($webApp in $mbeanServer->query("resin:type=WebApp,*")) {
  echo $webApp->name . "&lt;br>\n";
}
</example>

</s3>

</s2>

<s2 title="resin_debug">

<p>Write debugging information to the log.  The log is at INFO level.</p>

<example title="resin_thread_dump">
&lt;?php

$a = array("a", "b");

resin_debug("ARRAY: $a[0]");

?>
</example>

</s2>

<s2 title="resin_thread_dump">

<p>Produce a thread_dump to the logs.  The log is at INFO level.</p>

<example title="resin_thread_dump">
&lt;?php

$a = array("a"=>"b");

resin_thread_dump();

?>
</example>

</s2>

<s2 title="resin_call_stack">

<p>Returns an array containing the current PHP function call stack.</p>

<example title="resin_call_stack">
&lt;?php

function foo()
{
  bar();
}

function bar()
{
  var_dump(resin_call_stack());
}

foo();

?>
</example>

</s2>

<s2 title="resin_var_dump">

<p>Produce a var_dump to the logs.  The log is at INFO level.</p>

<example title="resin_var_dump">
&lt;?php

$a = array("a"=>"b");

resin_var_dump($a);

?>
</example>

</s2>

<s2 title="resin_version">

<p>Returns the version of Resin running Quercus.</p>

<example>
&lt;?php

var_dump(resin_version());

?>
</example>

</s2>

<s2 title="xa_begin">

<p>
Starts a distributed transaction.  All database connections will
automatically participate in the transaction.
Returns TRUE for success, FALSE for failure.
</p>

<example>
&lt;?php

xa_begin();

...

xa_commit();
?>
</example>

</s2>

<s2 title="xa_commit">

<p>
Commits a distributed transaction.  All database connections will
automatically participate in the transaction.
Returns TRUE for success, FALSE for failure.
</p>

<example>
&lt;?php

xa_begin();

...

xa_commit();
?>
</example>

</s2>

<s2 title="xa_rollback">

<p>
Rolls back a distributed transaction.  All database connections will
automatically participate in the transaction.
Returns TRUE for success, FALSE for failure.
</p>

<example>
&lt;?php

xa_begin();

...

xa_rollback();
?>
</example>

</s2>

<s2 title="xa_rollback_only">

<p>
Marks the current distributed transaction as rollback only.  Subsequent
attempts to commit the transaction will fail with a warning.
Returns TRUE for success, FALSE for failure.
</p>

</s2>

</s1> <!-- resin module -->

<s1 title="Quercus Internals">

<p>If you want to develop Quercus modules, the first step is to
download the source and look at the existing modules as an example.
All the PHP functions and classes are written as modules in the
Quercus system, so adding another one is straightforward.</p>

<s2 title="Strings and i18n">

<p>Since Java has 16-bit characters, PHP 5 has 8-bit characters, and
PHP 6 has 16-bit characters only in unicode.semantics='true' mode, the
Quercus classes for strings are a little complicated.  Here's the
list:</p>

<s3 title="StringValue">

<p><b>StringValue</b> is an abstract string class as the parent of all
strings in Quercus.  This class does not have any underlying
data.</p>

</s3>

<s3 title="StringBuilderValue">

<p>The main string class for PHP-5 mode for both string and binary data.
Strings are conceptually 8-bits like PHP5, but are stored as
16-bit Java characters for efficiency, i.e. because Java wants its
strings to be 16-bits.  The top byte will always be zero
for StringBuilderValue.  If the application is running in PHP5 mode,
your module will always use StringBuilderValue for both binary and
string values.</p>

</s3>

<s3 title="UnicodeBuilderValue (PHP6 unicode.semantics)">

<p>In PHP6 unicode mode, unicode strings are represented as
<b>UnicodeBuilderValue</b>, which are just like Java's 16-bit strings.
In PHP6 mode, you must always use <code>UnicodeBuilderValue</code> and never
<code>StringBuilderValue</code> because
<code>StringBuilderValue</code> is only for PHP5 mode.</p>

</s3>

<s3 title="BinaryBuilderValue (PHP6 unicode.semantics)">

<p>In PHP6 unicode mode, binary strings are represented as
<b>BinaryBuilderValue</b>, which are just like Java's byte arrays.
In PHP6 mode, you must always use <code>BinaryBuilderValue</code> and never
<code>StringBuilderValue</code> because
<code>StringBuilderValue</code> is only for PHP5 mode.</p>

<p>Note, that <code>UnicodeBuilderValue</code> and
<code>BinaryCodeValue</code>  are not equivalent, which can be
surprising when using them as keys to arrays.</p>

</s3>

</s2>

</s1>

<s1 name="resources" title="See Also">

<ul>
<li><a href="http://quercus.caucho.com">Quercus home page</a></li>
<li><a href="http://forum.caucho.com">Caucho Forums, including a Quercus forum</a></li>
<li><a href="http://bugs.caucho.com">Caucho Bug Tracker</a></li>
<li><a href="http://maillist.caucho.com/mailman/listinfo">Caucho Mailing Lists</a></li>
</ul>

</s1> <!-- see also -->

  </body>
</document>
