3

Background / The Problem

I need to make a (large) application with a certain set of core functionality, and certain functionality for multiple clients within it. Each client has different requirements and while they may share some functionality, I need to separate the code for each client, so a change to one won't affect others. Each client section of the application should also inherit some features from the core application. Ideally I would like to separate the databases for each client too. In terms of a user system, core users should be able to have access to each client's functionality, but client users should only be able to interact with their specific client section of the site.

Current Solution

Each client has its own subdomain and the MVC can override the core's MVC files IF they exist. In a nutshell, my custom MVC's autoloader checks the client directory for the matching M,V, or C file when a subdomain is present in the URL and loads that particular client's file INSTEAD OF the core file. It's an override ability in a sense.

Questions

  1. Am I solving this problem in a way that would be considered good practice in terms of software design?

  2. If I were to use an existing PHP Framework (I would like to), how might I go about setting it up to solve this problem? Specifically I have been looking at Yii and CodeIgniter.

Thanks in advance!

Update: I have discovered a design pattern called HMVC (Hierarchical MVC) and it seems to be essentially what I have described. I see that Kohana 3 is built using it and that Codeigniter has an extension that allows it.

0

3 Answers 3

1

This may or may not be of any use to you, but look at Symfony 2's "Bundle Inheritance". It allows you to override functionality from distributed bundles on an application level.

If you developed your core functionality in a bundle, you could deploy multiple applications and do the overrides there. Keep the core bundle in sync with via version control and a Composer repository, and the only things that would differ between these applications would be the client-specific modifications.

The downfall with this approach is that you're managing N deployed applications, which isn't exactly friendly. Perhaps you could fork Symfony 2 and alter the class loader to be client-aware so you can have multiple client folders in your application deployment. It should be a relatively simple fork, so keeping Symfony updated would be trivial.

2
  • It shouldn't be necessary to fork Symfony - a Symfony application can override any of the core Symfony classes without a fork. Mar 12, 2013 at 15:41
  • This is an interesting idea, thank you for the input. May 23, 2013 at 14:00
0

What you want is a form of dependency injection.

Try symbolic classes:

namespace Core;
class X { }
class Y { }

 

namespace MrSmith\Core;
class X extends \Core\X { } // extend specific core class for Mr. Smith

 

define('CLIENT_NAME','MrSmith');
$x = new \Sym\Core\X();
$y = new \Sym\Core\Y();

Have the autoloader see "Sym" in the namespace and load \MrSmith\Core\X and then alias it with \Sym\Core\X.

Then it attempts the same with \Sym\Core\Y, can't find one for Mr. Smith, and falls back to \Core\Y.

This way you only need to define deviations on a per-client basis, with each client in their own sandbox.

If you're deploying the system by giving each client a copy and they're sandboxed already in their own subdomain/document root, you could skip using CLIENT_NAME and just have it look in a "Sym" directory, and use "Sym" as the namespace instead of "MrSmith".

0

Working with CakePHP but doable in many different systems which are capable of some plugins concept.

What we do is develop the core functionality in plugins first.So for example: users management feature. That plugin is stored at GitHub as a separate repository.

The we create one general application setup, that is files like index.php, example css file etc. For each client install this basic setup and start loading plugins to get the desired features.

So in GitHub you have:

Template Application (index.php / example css file / pluginloader)
Plugin 1 (users management)
Plugin 2 (accounting)
etc.

The client application can be fully customized and use the features of the plugin as desired.

Then, to go further, you can even override a single view of a plugin. Example of that can be found here: http://book.cakephp.org/2.0/en/plugins.html#overriding-plugin-views-from-inside-your-application

If you like you can get the copy of the template and then push it as a new repository at GitHub so you get in the end all separate repositories loaded together.:

Template Application (index.php / example css file / pluginloader)
Plugin 1 (users management)
Plugin 2 (accounting)
Plugin 3 (custom feature for Client 1 - link to their production site)
etc.
Client 1 (you're first copy of template)
Client 2 (the second copy of template)

Nice thing is also that you have separate modules which can be tested separately, re-used etc.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.