views:

798

answers:

3

Hi,

We are developing an e-commerce platform utilizing the Zend Framework. We have several instances of the application up and running, using the same code base. Config settings are used in order to differentiate the various shops.

The challenge we are facing, is that we want to keep the general platform as it is now, and extend it rather than use the configuration approach outlined above. The general platform (or base application) should contain common controllers, models and views. Custom functionality (controllers, models and views) specific to the particular instance, should be contained in a separate extension and in a way plugged into the core platform. This way, the shared code base is kept clean and not over bloated.

Does anyone have any experience with such a approach? Are there any best practices around?

Any pointers are much appreciated!

A: 

We operate a software as a service application which sounds similar to your platform and in our case all instance data is stored in the instance's own database.

As for dealing with custom functionality (code), if it's entirely bespoke then I guess it would make sense to modularise or package the custom code into a container which can be referenced by the customer's unique identifier and load the code on demand. This is simple for modules but obviously more complicated if you wanted individual controllers or even actions.

Some systems build in their own event/callback system that allow functionality to be injected, though this is more common for public APIs.

David Caunt
Thanks for your response! Custom functionality is entirely bespoke, hence it should not be merged into the core code base. Typically, custom functionality consists of both controllers, actions, models and views. Ideally, the solution we're looking for is a way to extend an existing Zend Framework web app with custom controllers, models etc.
Agora
A: 

EDIT: I hadn't noticed the various comments. So the code that is customized is not in one single package, and it adds functionality and doesn't override.

The problem here is that you mention the code does not override anything, but rather adds functionality. You'd probably be looking at some form of a plugin system, where you'd read a configuration file with class names. Those classes would provide information about each plugin (i.e. if your UI uses tabs, it would have a property for the tab's name).

It really depends on what kind of functionality is different per implementation. It might be helpful to have more information to provide a high level solution.

The way I use PHP autoload (see: http://stackoverflow.com/questions/779123/how-does-oop-manage-to-include-classes-stored-in-different-files/787233#787233) creates separate folders depending on the class name. This might be helpful in separating out the code from other implementations.

Jordy Boom
Thanks! I'll look into your PHP autoload reference.
Agora
+1  A: 

I've been looking at the same issue recently at my agency and the solution I'm currently testing involves the following app folder structure:

app/
    default/
            controllers/
            models, etc
    ecommerce/
              controllers/
              models, etc
lib/
    S24/
        ComponentCode.php
modules/
        ecommerce/
                  admin/
                        controllers/
                        models, etc
                  default/
                          controllers/
                          models, etc
data, public web, temp, other ZF folders

The idea is common component code is stored in the lib, the modular application is stored in modules and the individual client website code is stored in app.

The lib/S24 and modules/ecommerce folders would be common and the same for each project (we SVN external these folders).

app is a module directory, so the default, and ecommerce folders create modules within ZF. app/default is for the default (i.e. no module) controllers. app/ecommerce would contain a set of controllers that simply extend controllers within modules/ecommerce/default/controllers.

You can then extend functionality in the app/ecommerce/controllers if you wish, or add new functionality.

Since we want to keep the module admin system the same and also support multiple admin systems (in URLs like www.domain.com/admin/ecommerce and www.domain.com/admin/user) we serve the modular admin system directly from the modules folder. Any custom admin pages can then be added to app/admin/controllers.

// Add Controller folder
$front->addControllerDirectory('/path/to/modules/ecommerce/admin/controllers', 'ecommerceAdmin');

// Add route
$router->addRoute(
    'ecommerceAdmin',
    new Zend_Controller_Router_Route('admin/ecommerce/:controller/:action',
                                     array('module' => 'ecommerceAdmin', 
                                           'controller' => 'index',
                                           'action' => 'index'))
);

As I say I am currently testing this but I hope it gives some ideas for your own system. Once I've got this completely stable I hope to write up a blog article on the topic.

simonrjones