Sebastian Kuligowski's Home Page

Decorating PHP content with SiteMesh

October 4th, 2009

After searching the Internet I found there is no easy way to integrate SiteMesh decoration framework with PHP content. I decided to develop it by myself to have it done for any future projects. Read my tutorial to find out how to decorate PHP content with SiteMesh in 5 minutes.

Solution overview

First of all SiteMesh is only the integration and decoration framework, so do not expect from it to send a request to your PHP site - you should do it for yourself. I've implemented SitemeshProxyFilter for this purpose. This filter is responsible for requesting PHP sites using prepared proxy URL. It allows you to add custom headers to the proxy request and do with proxy response whatever you need. SitemeshProxyFilter bases on code coming from org.mortbay.proxy.AsyncProxyServlet and uses Jetty's HttpClient to make remote requests.

Working example

I've prepared working example of PHP and SiteMesh integration. You can download it from here: sitemesh-php.zip. It is a maven based project, so after downloading you have to invoke mvn eclipse:eclipse command to create Eclipse project files. 

Prepare Apache Httpd Web Server with PHP

I assume you have Apache Httpd Web Server with PHP installed on your host (if not, use some of integrated Apache+PHP+MySQL pack to ease the process of installation, eg. WampServer). 

Now place sitemesh-php/src/main/php/index.php in your document root of Apache Httpd Server. This file should be accessible from following url: http://127.0.0.1/index.php.

Running example on Apache Tomcat Server

Build appliaction using following command: mvn install. Now simply copy target/sitemesh-php.war file to Tomcat webapps directory and start the server. Application is now accessible from the following url: http://127.0.0.1:8080/sitemesh-php/.

Step by step

Description of available decorators

First of all we have to define available decorators by creating decorators.xml file. 

<decorators defaultdir="/decorators">
    <decorator name="page" page="page.jsp">
          <pattern>/*</pattern>
    </decorator>
</decorators>

There is only one decorator (page) defined and placed in /decorators directory. All requests should be decorated with page decorator because "/*" pattern is used.

Define custom decorator

The next thing we should do is the decorator file. We create for this purpose page.jsp file (placed in /decorators directory).

<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %>
<html>
<haed>
	<title>Sitemesh decorating PHP page</title>
</head>
<body>
<div style="background-color:#aef">Menu in Java</div>

<decorator:body />

<div style="background-color:#aef">Footer in Java</div>
</body>
</html>

The decorator's content is really straightforward. It's simply the skeleton of html file with menu and footer div blocks added. The content of PHP site will be inserted in place of <decorator:body /> tag.

Implement PhpFilter proxy class

The last thing is to retrieve PHP content from previously launched Apache Web Server. We have to create PhpFilter proxy class and define, how to get desired content.

package pl.kuligowski.sitemeshphp;

import java.io.IOException;
import javax.servlet.http.HttpServletRequest;

public class PhpFilter extends SitemeshProxyFilter {

	@Override
	protected String proxyHttpURI(HttpServletRequest request) {
		return "http://127.0.0.1/index.php?myParam="+request.getRequestURI();
	}
	
	@Override
	protected void onProxyRequestHeaders(HttpServletRequest request, HeadersHolder headers) 
           throws IOException {
		headers.addHeader("X-My-Header", "Hello from Java World");
	}

}

PhpFilter should extend SitemeshProxyFilter class which covers all proxy/connection stuff. The only one method you should override is the proxyHttpURI method, which contains proxy url construction logic. You can use any data from original HttpServletRequest, especially request's parameters.

By overriding onProxyRequestHeaders method you can add custom headers to the proxy request. Custom headers could be used by php site (for example to identify that the request is from Java server). 

Finally you can override doProxyHttpFilter method to control proxy response, statuses and returned content. If such method is not implemented, returned content and headers are copied to the original response (also all redirects and error statuses). For more information read java docs of the SitemeshProxyFilter class.

After implementing proxy filter, we should create its definition in web.xml file.

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

	<filter>
	    <filter-name>sitemesh</filter-name>
	    <filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class>
	</filter>

	<filter-mapping>
	    <filter-name>sitemesh</filter-name>
	    <url-pattern>/*</url-pattern>
	</filter-mapping>

	<filter>
	    <filter-name>phpFilter</filter-name>
	    <filter-class>pl.kuligowski.sitemeshphp.PhpFilter</filter-class>
	</filter>

	<filter-mapping>
	    <filter-name>phpFilter</filter-name>
	    <url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>

PHP scirpt

Let's take a look how to retrieve data passed from Java server to PHP site.

<div style="background-color: #eee">
	Hello from PHP World <br />
	myParam = <?php echo $_GET['myParam']; ?> <br />
<?php
	$headers = apache_request_headers();
	echo("X-My-Header = " . $headers['X-My-Header'] . "<br />");
	$jSessionId = isset($_COOKIE['JSESSIONID']) ? $_COOKIE['JSESSIONID'] : "do refresh";
	echo("JSESSSIONID is also passed = " . $jSessionId . "<br />");
?>
</div>

 As you can see, all passed data can be accessed in PHP script, including JSESSIONID which is placed in $_COOKIE array.

Results

If you run presented example you should see following results on the screen:

Where can I use it?

Decorating PHP content with Sitemesh is useful if you want to share session between Java web application and php application (such as Wordpress blog or any opensource forum). You save a lot of time by taking ready and working PHP applications.

Presented soulution is also scalable. Your proxy could realize load balancing between several PHP web servers.

Download

You can download maven based project of presented example from here: sitemesh-php.zip.

1 comments to "Decorating PHP content with SiteMesh"

Add comment

 (will not be published)
Contact me

Page generated in 0.021s / 

Sebastian Kuligowski's Home Page

Copyright © Kraków, 2008 All Rights Reserved