Where I don't care what others think

PHP on Google App Engine

April 9th, 2009 Posted in Uncategorized

Warning:  I am not an expert on anything that I did here to make PHP work, nor am I likely following the best practices for doing something like this.  Experiment at your own risk.

I’m going to cut to the chase here.  If Ruby on Rails can run on Google’s App Engine (via JRuby) I figured that there is no reason why  PHP shouldn’t be able to work.  Of course I wasn’t interested in writing my own PHP interpreter in Java or something like, so I used Google to find Quercus.

Using the instructions to get JRuby working, as well this very useful guide about getting Groovy to work, I set off to piece together something for PHP using Quercus.  My biggest problem during this whole process was extracting the jar’s I needed.  For some reason, anything I downloaded from the quercus website wouldn’t extract correctly on my Mac or my PC… with the specific quercus.jar file being corrupt.  After dropping them into my war/WEB_INF/lib folder and starting my Web Application (I’m using Eclipse FYI) I would get errors about zip not being able to do its job.

Google helped me find a SVN repo out there that had the 3 jars I needed, and  after loading them into the correct folder. Eclipse stopped throwing errors.  If you’re looking for the files I used, you can find them here: http://lportal.svn.sourceforge.net/viewvc/lportal/portal/trunk/lib/development/.  I determined that quercus.jar, resin_util.jar, and script-10.jar were needed for Quercus to do its thing correctly… at least that’s what I think.  Drop them in the WEB_INF/lib folder and you should be all set.

Configuring PHP to work was surprisingly easy.  Edit web.xml to have the following lines:
<servlet-name>Quercus Servlet</servlet-name>

<servlet-name>Quercus Servlet</servlet-name>

I don’t know if any order is important here, but I put the php servlet first, followed by the default servlet, followed by the php servlet-mapping, followed by the default servlet-mapping.  By default I mean the one that was generated for me when they thought I wanted to use Java.

Next on the to-edit list was appengine-web.xml.  I can’t take credit for knowing to do this, I read it on purrrgatory’s twitter. I added the following lines, right after the close of the system-properties tag.
<exclude path="/*.php" />
<include path="/**.php" />

Looking back at that file I wonder if my exclude path is correct…. but hey its working.  I’m not going to complain.  I created a php.ini, which is completely blank at the moment, in war/WEB_INF.  I think I can put stuff here later.

The last step: write some PHP.  I through together the lamest test php file I could imagine, and saved it as war/index.php.

Initially when I tested this out I was getting a wierd error about org.mortbay.util.ajax.Continuation not being there.  I don’t know what that is, but its included in the jetty-util-6.1.0.jar file, which I found here.  I’m unsure if this is specific to the development platform (where I know jetty is used) or required somewhere in the Quercus mix.

Once in a blue moon, when I start the application up I get an error “java.lang.ClassNotFoundException: `org.mortbay.jetty.handler.ContextHandler’ not valid: java.lang.ClassNotFoundException: org.mortbay.jetty.handler.ContextHandler” but refreshing the page seems to clear that up.

I deployed to Google App Engine and everything worked perfectly! (http://txter.appspot.com/)

Of course I quickly remembered the JDBC wasn’t supported, so in turn the database wrappers that I could easily enable from Quercus weren’t going to work.  I’ll play around with this more, trying to figure out how to get it to interact with DataStore or something.

Here are some screenshots incase you’re as confused as I was when I started out with all this.

And I’ve uploaded my war directory, incase its of any help.

Best of luck!

— UPDATE 1 —

Initially, I was very wearsome of getting PHP to talk nicely with the datastore.  Doesn’t look like it will be too bad to sort out.  I’ll post a more detailed post about getting the datastore to work cleanly… maybe with a nice php or java wrapper class, but for now I’ve posted some sample code here .  The two .java files went in my source/projname/ directory, and the php file went with the other PHP files.

  1. 28 Responses to “PHP on Google App Engine”

  2. By J Stanley on Apr 9, 2009

    Great work, works like a charm. I paired this up with the urlrewrite jar and added mod_rewrite style url rewriting for my app as well. Thanks again!

  3. By Arwed Schmidt on Apr 10, 2009

    Thanks! I’m going to reproduce your project and test out how the PHP-Support is.


  4. By Arun on Apr 10, 2009

    Awesome! I am trying it right now. Thanks a ton. I guess we need some libs to work with datastore, memcache etc. for PHP.

  5. By J Stanley on Apr 10, 2009

    Memcache is actually quite easy to integrate with:

    import com.google.appengine.api.memcache.MemcacheService;
    import com.google.appengine.api.memcache.MemcacheServiceFactory;
    import com.google.appengine.api.memcache.Expiration;

    $service = MemcacheServiceFactory::getMemcacheService();

    $expiration = Expiration::byDeltaSeconds(60);
    $service->put(“myKey”, “myValue”, $expiration);

    echo $service->get(“myKey”);

  6. By John Turner on Apr 10, 2009

    Can some one post a zip of their complete app. i’mhaving trouble getting this to work.

  7. By Arwed on Apr 12, 2009

    Sure, here you are:

  8. By John Turner on Apr 12, 2009

    Thx , works like a champ!

  9. By John Turner on Apr 12, 2009

    How can I get a php file to execute that’s int a sub folder off the root

  10. By Arwed on Apr 13, 2009

    Try to change your appengine-web.xml to something like this:

    It seems like you have to repeat the -Part once every level of folder-structure.

    I’m not sure whether there isn’t a more easier way but it works.

    – Arwed

  11. By Arwed on Apr 13, 2009

    Blog removed xml… look this paste-it:

  12. By derak on Apr 26, 2009

    Great post.

    Have you figured out how to read from a datastore with php yet?

  13. By James on Apr 27, 2009

    I have the same question with derak!

    I hope so u can figured out how to read from a datastore with php!!

  14. By jordan314 on May 12, 2009

    Hi Brian,
    Thanks so much for publishing this.
    I’m trying to run the facebook PHP SDK, and have a couple questions.
    I don’t think the lportal repository you link to has the most recent version of quercus. The facebook API gives me a nullpointerexception on urlencode which I believe has been fixed. When I disable that part of the code, I get a methodnotimplemented error related to curl and urlstreamhandler. Caucho says it has run the facebook SDK successfully, so I’m not sure what my problem is.
    I tried putting the newest quercus-3.2.1-src.jar in my lib folder instead of quercus.jar but then the servlet blows up. Should I try the war instead? I’m not quite sure how to do that.
    Also, I get 403 forbidden errors unless I link directly to my index.php file. HTML files also override the PHP files if there are any in the directory. How did you get your app to automatically resolve to index.php?
    Finally, has anyone gotten the ContextHandler error to go away?

  15. By Mark Essel on Jul 24, 2009

    Heyo, thanks for sharing your experiences using resin/quercus. I’m still kinda shocked that google app engine doesn’t support php code. I suppose I could rewrite what I have in python but I’m still learning and would prefer learning more python when I’m setting up my oauth pages (have barebones for friendfeed, have to do the same for facebook/twitter).

  16. By Radhika on Nov 30, 2009

    I am trying to communicate with php, I followed the same steps but when I run localhost it displays blank screen.
    Can you please list the steps to be followed with screen shots and examples?

  17. By jpc on Feb 22, 2010

    Hi, the script show no matching class PMF error.

  18. By Keerthi on Mar 24, 2011

    Thanks for pointing out java.lang.ClassNotFoundException: `org.mortbay.jetty.handler.ContextHandler’ issue… it worked for me… nice solution 😀

  19. By Keerthi on Mar 24, 2011

    Anyway refreshing page is not a solution for java.lang.ClassNotFoundException: `org.mortbay.jetty.handler.ContextHandler’ issue.

    1. Download jetty from http://jetty.codehaus.org
    2. Extract the archive.
    3. Copy 2 files jetty-6.1.26.jar / jetty-util-6.1.26.jar from jetty lib folder to your application’s lib folder (in WEB-INF).

  20. By Pierre on Aug 25, 2011

    Thanks a lot for this article my php application is hosted on GAE. The only problem i have is with the CAPTCHA feature. I am using an open source solution called “Securimage” (www.phpcaptcha.org/)
    i use another php to instantiate the class and show a CAPTCHA image. It was working on my local Apache server but it’s not working on GAE it just display the following message:
    Error: Server Error
    The server encountered an error and could not complete your request.

    If the problem persists, please report your problem and mention this error message and the query that caused it.

    Can someone help?? Thank you

  21. By sang on May 28, 2012

    can anyone send me the complete app ( PHP WITH DATASTORE in gae). I couldnt find the solution in finishing the app ????
    or any links to some sample apps ( wer source code is present)

  1. 8 Trackback(s)

  2. Apr 14, 2009: ???PHP?Google App Engine??? « .::???::.
  3. Apr 17, 2009: Google App Engine con soporte PHP, Carrero
  4. Apr 26, 2009: Derak » Quercus and App Engine - Reading from the data store.
  5. Jul 24, 2009: Web Programming Foo
  6. Jan 13, 2011: PHP in Google App Engine
  7. Feb 11, 2011: A Ning Network + RSS Feeds + PHP cUrl + MySql + GAE -> WTF?! « Mostly Harmless
  8. Apr 4, 2011: ???PHP?Google App Engine??? | ??????
  9. Apr 4, 2011: ???PHP?Google App Engine??? | ??????

Post a Comment