Friday, May 27, 2011

Using Zend framework MVC in a subdirectory of an existing project

I like MVC frameworks. Zend framework isn't my favorite, but my company is using [an older] Zend framework for it's mobile site. I might as well stick with it. Unfortunately, the desktop web site is still a jumbled mess of plain old PHP scripts with logic, database calls, and HTML in a single file. So what does one do when they want to develop new features in an MVC framework? Create a new virtual host just for those features? (This is how our mobile site works, it's in /var/sites/example.com/mobile) Create your own framework or use one that was designed for standalone use? No, you figure out how to use the newest version of the Zend framework from within a subdirectory of the current site!!

Research

First, a quick trip to google.. this looks promising Zend Framework Run in a Subdirectory ... it's a dead link.. crap.. Well, I guess I should just try it and see what happens.

Experiment

I used the zf.sh command line tool to create a ZF project in a subdirectory /var/sites/example.com/zf_test. Changed my .htaccess file to include "RewriteBase /zf_test/public/" and then fired up Chrome and hit the URL.

Of course I got a blank white screen and a PHP error message. The odd part was the PHP error had a call stack in the mobile site's bootstrap file.. hmm... So the problem was that APPLICATION_PATH and APPLICATION_ENV where already being defined in the mobile site's code and for some reason (I'm still not sure why) the mobile site's bootstrap was being called. So I changed them to DESKTOP_APPLICATION_PATH and DESKTOP_APPLICATION_ENV in zf_test/public/index.php and zf_test/config/application.ini.

Save, upload, restart apache for good measure, and hit refresh.

PHP Fatal error: Undefined class constant 'EXCEPTION_NO_ROUTE' in ... Hmm... a quick trip to google helped me find this was because the version of zend framework on the server on the one on my development box where a bit off. So, can I include the full ZF library in the project locally like I can with Rails? Yep, and almost as easily. I simply copied the
library/Zend folder from my local install to zf_test/library, uploaded, refreshed :

PHP Fatal error: Cannot redeclare class zend_loader in ... Okay, so something is initializing the old zend loader before my new zend framework can (dang "php_value auto_prepend_file ..."). Well, there can't be that many differences between the versions of zend loader can there? Let's just get rid of the new one and let the old one handle loading.
rm -rf /var/sites/example.com/zf_test/library/Zend/Loader*

Refresh and ... An error occurred Page not found

I'm starting to get annoyed. Okay, it looks like it's actually loading something in the App. After a bit of playing around, I set resources.frontController.params.displayExceptions = 1 and find that it's searching for a controller called zf_test. That's what I was afraid would stop the subdirectory thing from working. I google and find Base URL and subdirectories that sounds promising. So, added to index.php :

<?php
$ctrl  = Zend_Controller_Front::getInstance();
$router = $ctrl->getRouter();
$router->setRewriteBase('/zf_test');

PHP Fatal error: Call to undefined method Zend_Controller_Router_Rewrite::setRewriteBase() in ... &^$%$#&@$#!^&*!! I dig into the ZF front controller code and find it has a function setBaseUrl() that is passed to the router. Well, that's easy.

<?php
$ctrl  = Zend_Controller_Front::getInstance();
$ctrl->setBaseUrl('/zf_test/');

Save, upload, refresh...

Success!!



Find something else to work on

Okay, now I'm tired of playing with Zend Framework in a subdirectory of a project. I'll implement something in it later.

No comments:

Post a Comment