PHP insights, tips and tricks

Two (or more) Zend Framework projects on a shared host

Shared hosting environments can be a nightmare when it comes to PHP Web Development, specially in testing stages. Yes, I know one should not be using and paying for a hosting plan if the code is still not production ready, but I have seen some cases.

I will try to show how to have the Zend Framework installed with as many projects as you want (if your server quota allows you to) in the same web space and all these projects sharing the same ZF copy.

Suppose that your home directory is /home/mauricio/. From now on, I am going to refer to it as <root>. Create the following file structure under it:

library/
  Zend/
myfirstproject/
  application/
    controllers/
    views/
      scripts/
mysecondproject/
  application/
    controllers/
    views/
      scripts/
public_html/
  myfirstproject/
  mysecondproject/

Now download, extract and upload the “Zend” directory contained in the zip or gz file into the “<root>/library” directory of the structure that you have just created. This copy of the Zend Framework will be shared by all projects. If needed, you can upgrade to a future version of ZF just by changing its content.

Keep in mind that this example is based on the fact that the public folder on the hosting environment is “<root>/public_html”. Some providers call it “www”, so… in this example our public folder will be called “public_html”, make the appropriate changes to suit your needs.

The first folders: “myfirstproject” and “mysecondproject” will contain the application files that won’t be visible to the outside world. Notice that under public_html exist another two folders under the same names, these two folder will contain the bootstrap or the entry point for the application which must be of public access and all the images, style sheets and other media that your application requires.

Your .htaccess file under <root>/public_html/myfirstproject/ should look like this:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]

And the bootstrap file index.php under the same location, should look like this:

<?php
/**
* <root>/public_html/myfirstproject/index.php
*
*/

// The library folder contains Zend Framework files
define('LIBRARY_PATH',     realpath(dirname(__FILE__) . '/../../library/'));
define('APP_PATH',         realpath(dirname(__FILE__) . '/../../myfirstproject/application/'));
define('CONTROLLERS_PATH', APP_PATH . '/controllers/');

// library is appended to the include_path
set_include_path(get_include_path() . PATH_SEPARATOR . LIBRARY_PATH);
include_once 'Zend/Loader.php';
Zend_Loader::registerAutoload();

/**
* The most important step is to set the controllers directory pointing to
* <root>/myfirstproject/application/controllers
*/
$front = Zend_Controller_Front::getInstance();
$front->setControllerDirectory(CONTROLLERS_PATH);
$front->dispatch();

That was the trick, let’s finish this creating our IndexController and its view. The first one should be placed on <root>/myfirsproject/application/controllers/IndexController.php:

<?php

/**
* <root>/myfirstproject/application/controllers/IndexController.php
*
*/
class IndexController extends Zend_Controller_Action
{
  public function indexAction()
  {
  }
}

The view should be anything you like, my bet is for:

<!-- <root>/myfirstproject/application/views/scripts/index.phtml -->
<html>

<head><title>It works!</title></head>

<body>
<h2>It works!</h2>
</body>
</html>

That’s all, you can start building more views, controllers and helpers. To get your second project working just follow the same steps that you did for “myfirstproject” folder. The same way, you can create as many projects as you want, keep in mind that they all share the same Zend Framework library.

Tags: , ,

23 Comments

rssComments RSS transmitTrackBack Identifier URI


Great article.

If one has shell access to a host (through a provider like Slicehost), may I suggest that an easier alternative would be to create a symbolic link to a common ZF folder. For instance, assuming the following directory structure under /var/www (or wherever your files exist):

/var/www/zf-1.7.7
/var/www/project1
/var/www/project2

…it is trivial to go into each project’s Library (e.g., cd /var/www/project1/library) folder and do the following:

ln -s /var/www/zf-1.7.7 Zend

Now, whenever a new version of the framework is released, all you have to do is add the new files into that zf-1.x.x folder.

Comment by Aaron on March 25, 2009 6:14 pm


I prefer single copies of library folder… That makes possible indipendente upgrading and indipendent patching, as not all of the projects would want to upgrade the version of zf at the same time (for example after upgrading I have to run unit and integration tests, and so I can do this on a per-project basis).

Comment by Giorgio Sironi on March 25, 2009 6:35 pm


I do things slightly differently. I have the ZF framework , Smarty and our own CMS framework (based on ZF of course) in a separate library well outside of web root.
In my boostrap I do:

//Define the library path
define(”LIB_PATH”,DIRECTORY_SEPARATOR . “usr” . DIRECTORY_SEPARATOR
. “local” . DIRECTORY_SEPARATOR .”Frameworks” . DIRECTORY_SEPARATOR. “lib”);
//modify include path - add library root path - needs to be hard coded
ini_set(’include_path’,ini_get(’include_path’) . PATH_SEPARATOR . LIB_PATH);
//find web root path
$root = dirname(dirname(realpath(__FILE__)));
define(”ROOT_PATH”, $root);
require_once ‘Zend/Loader.php’;
Zend_Loader::registerAutoload();

Zend Framework is stored in /usr/local/Frameworks/lib/Zend
Smarty gets stored in /usr/local/Frameworks/lib/Smarty
Our framework in /usr/local/Frameworks/lib/Ourfw

on so on.

The Zend_Loader takes care of everything and by using the ROOT_PATH constant you can add controller and model paths etc at will. Each application then sits in its own vhost on the server using the standard ZF layout

httpdocs -> public files including index.php, js, css etc
application -> config, modules, language, cache etc
modules -> controller, model, view, language

Works a treat for us and supports myriad sites. Hope it helps others.

Comment by Ashley Kitson on March 25, 2009 7:39 pm


@Aaron: symbolic links are a great option, it may cause a little bit of overhead on older filesystems and its better to avoid them if performance is a concern.

@Giorgio Sironi: in terms of portability and backwards compatibility, carrying the whole library on each project is a good approach. Each case has its ups and downs.

@Ashley Kitson: thanks for the tip! The only problem with it is that you need root access to the server, in my case I’m trying to deal with shared hosts, where your ability to control stuff is limited.

Comment by Mauricio Cuenca on March 25, 2009 8:37 pm


Nice article, Mauricio

But why in the directory structure application and controllers in some level?

Comment by Oleg Lobach on March 25, 2009 10:02 pm


This is a very useful approach. Keep up the good posts!

Comment by Mauricio Morales on March 25, 2009 10:54 pm


@Oleg Lobach: You were right, the structure did not display correctly in some browsers. I fixed it. Thanks!

Comment by Mauricio Cuenca on March 26, 2009 12:17 am


Like aaron I was thinking about symlinks but the overhead mentioned is a good point. A setup like this might also be applicable on a company owned dedicated server that hosts a lot of (smallish) website. As the number of projects increases it becomes increasingly important that not all application neccessarily share the same library version.

I would suggest (as an extension to the layout in the article) something like this:

/sharedlib/zend/1.7.0/Zend
/sharedlib/zend/1.7.7/Zend

Per application you can then point your include-path to the right version. (In theory the additional Zend folder wouldn’t be neccessary but Zend_Loader likes it very much)

Comment by Tibo Beijen on March 26, 2009 10:04 am


@Mauricio Cuenca - perhaps you could try the approach of setting up a dummy website and use that to store all your libraries, then point your library path at that.

@Tibo Beijen - I actually think it is very important that all sites share the same version of base libraries. You wouldn’t run different sites on different versions of PHP unless absolutely necessary, so why do it with framework code? If you need to vary stuff, subclass it in your application. We are lucky enough to have a full dev -> test -> production staging setup, so we can run tests before deploying upgrades to the various libraries. The reality with ZF (in our experience) is that new versions of the library rarely break anything and when they are likely to, the ZF team do give notice in the release notes. They maintain backward compatibility very well. Just my opinion and not necessarily correct for all scenarios ;-)

Comment by Ashley Kitson on March 26, 2009 2:58 pm


[...] Zend Developer Zone has pointed out a recent blog post from Mauricio Cuenca showing how to run two (or more) Zend Framework applications on one account on [...]

Pingback by Mauricio Cuenca’s Blog: Two (or more) Zend Framework projects on a shared host | Development Blog With Code Updates : Developercast.com on March 26, 2009 5:11 pm


[...] Zend Developer Zone has pointed out a recent blog post from Mauricio Cuenca showing how to run two (or more) Zend Framework applications on one account on [...]

Pingback by Mauricio Cuenca’s Blog: Two (or more) Zend Framework projects on a shared host : WebNetiques, LLC : Website Developers in Minneapolis, MN on March 27, 2009 6:49 am


[...] Zend Developer Zone has pointed out a recent blog post from Mauricio Cuenca showing how to run two (or more) Zend Framework applications on one account on [...]

Pingback by Mauricio Cuenca’s Blog: Two (or more) Zend Framework projects on a shared host : Dragonfly Networks on March 27, 2009 6:51 am


[...] Focus on PHP » Archive » Two (or more) Zend Framework projects on a shared host (tags: zend) [...]

Pingback by links for 2009-03-27 « sySolution on March 27, 2009 5:00 pm


I am using this approach

/library/Zend-1.7.0/Zend
/library/Zend-1.7.7/Zend

Comment by Slavi on March 27, 2009 5:04 pm


[...] Two (or more) Zend Framework projects on a shared host [...]

Pingback by ??????? » [Web] ???? on March 27, 2009 10:22 pm


document good

Comment by hoangnd on March 28, 2009 4:19 am


Mauricio, gracias por el articulo. Tengo la estructura de directorios que mencionas en el blog y me funciona correctamente con dos proyectos diferentes, pero en los dos quiero hacer una pagina de login. Queria saber como puedo hacer con Zend_Auth que en cada proyecto tenga una sesion diferente. Mi problema esta en que si me logueo en un proyecto despues si quiero ir al otro no me aparece la pagina de login, sino que entra directamente.

Gracias!

Comment by Guillermo on April 21, 2009 4:52 pm


Hello Guillermo, aunque lo del Zend_Auth no tiene nada que ver con esto. Puedes cambiar el nombre de la sesión en cada instancia propia del módulo que autentica, sería algo como esto:

$firstengine = new Zend_Auth_Storage_Session(’ModueloA’);
$authorize = Zend_Auth::getInstance();
$authorize->setStorage($firstengine);

Igual haces para el otro, cada uno con un nombre de sesión diferente, como ‘ModuloB’. Así serán autenticadores independientes y el uno no interferirá con el otro.

Comment by Mauricio Cuenca on April 21, 2009 6:08 pm


Gracias! Me voy a fijar.

Comment by Guillermo on April 21, 2009 7:44 pm


Hi Mauricio
great tutorial, thank you, I followed it, and it works, except that I get an error if I put index.phtml in /application/views/scripts/
it works only if a put index.phtml in /application/views/scripts/index/

Comment by Marco on June 4, 2009 3:13 pm


Mauricio, mil gracias por el aporte. Tengo la siguiente inquietud: He configurado el Zend, para que me imprima el “Hola Mundo” con la url http://localhost/planeacion, pero necesito utilizar esta misma configuración, (de Alias en especial) para que cuando digite http://localhost/planeacion/aplicacion1…2…3...
Pueda ver la aplicacion1…2…3…, que son desarrollos que ya he logrado, pero que no me permiten configurar mas Alias en el config de apache (por “politicas”) gracias a tu idea de colocar un directorio independiente para cada aplicación en el public/aplicacion1…2…3…, he logrado presentar el siguiente error:
Fatal error: Uncaught exception ‘Zend_Controller_Dispatcher_Exception’ with message ‘Invalid controller specified (planeacion)’ in C:\Desarrollo\planeacion\library\Zend\Controller\Dispatcher\Standard.php:241 Stack trace: #0 C:\Desarrollo\planeacion\library\Zend\Controller\Front.php(934): Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http), Object(Zend_Controller_Response_Http)) #1 C:\Desarrollo\planeacion\prestadores\library\Base\Application.php(209): Zend_Controller_Front->dispatch() #2 C:\Desarrollo\planeacion\public\prestadores\Index.php(13): Base_Application->run() #3 {main} thrown in C:\Desarrollo\planeacion\library\Zend\Controller\Dispatcher\Standard.php on line 241.

La verdad, sé que algo de concepto tengo bastante mal, me gustaría que me guiaras en este inconveniente.

Entre otras si digito http://localhost/planeacion perfectamente imprime el “Hola Mundo”.

Comment by Carlos Andres on October 15, 2009 12:45 am


Hola Carlos Andrés, la forma más sencilla es crear un controlador para cada aplicación. Si quieres algo más especializado, puedes echarle un vistazo al Zend_Controller_Router.

Comment by Mauricio Cuenca on October 15, 2009 9:38 am


Very nice article. I was wondering the best solutions for multi projects on single host. After this article finally I will sleep well.
Regards from Poland ;)

Comment by Jacob on December 14, 2009 2:25 am

addLeave a comment