Vous avez développé une application PHP complexe (ou pas).

Le succès de votre application auprès de votre client (interne ou externe) vous amène à devoir décliner votre application dans plusieurs versions :

  • une pour votre client historique
  • une pour un nouveau client (concurrent de l'autre ?!)
  • une "marque blanche" pour démontrer les fonctionnalités de votre application en mode démo
  • ...

Votre application n'a pas été prévu pour cela, vous avez donc plusieurs options :

  1. dupliquer le code, purement et simplement
  2. mutualiser le code, et l'altérer pour qu'il gère les différences entre les versions (marques)

La première solution, bien que potentiellement plus rapide à mettre en oeuvre, se révèle couteuse dans le temps car il faut maintenir deux versions de l'application en parallèle (et répercuter les fix de bugs sur les différentes versions,...).

Pour implémenter la deuxième solution, il vous faut principalement :

  • externaliser les paramètres de configuration de l'application susceptible de changer en fonction de la version (connexion base de données, nom du client...)
  • mutualiser le code du coeur de l'application (i.e. la logique)
  • spécialiser la charte graphique (pour tel ou tel client ou version)
  • ajouter des "plugins" spécifiques à votre application qui seront spécifiques à telles ou telles versions (pour tel ou tel client)

Concrètement, il s'agit pour vous à minima (si il s'agit de la même application fonctionnellement) pour chacune des versions de :

  • donner un nom de code à votre version, ex: client1
  • créer un virtual host Apache spécifique, ex: client1.mondomaine.com
  • réaliser un fichier CSS spécifique, ex: styles/client1.css
  • réaliser un fichier JS spécifique, ex: scripts/client1.js
  • réaliser un fichier de configuration spécifique, ex: configs/client1.php
  • réaliser un fichier d'initialisation PHP spécifique, ex: inits/client1.php

Vous faites ensuite pointer tous les Virtual Hosts sur le même DocumentRoot (i.e. il n'y a qu'une seule application, un seul répertoire racine) définissez ensuite à l'intérieur du virtual host de chacune des versions une variable d'environnement dont la valeur prend le nom de code de la version, par exemple :

SetEnv APP_NAME client1

Ensuite au début de (chacun de vos|votre) scripts?, vous pouvez récupérer la valeur de cette variable d'environnement et la positionner dans une constante :

<?php

define('APP_NAME',$_SERVER['APP_NAME']);
...

Vous disposez maintenant d'une constante disponible dans tous vos fichiers inclus qui contient le nom de l'application, elle peut servir pour charger les bons fichiers :

<?php

require_once dirname(__FILE__).'/../configs/'.APP_NAME.'.php';
require_once dirname(__FILE__).'/../inits/'.APP_NAME.'.php';

...
// la logique de votre application ici
...
?>
<html>
    <head>
        ...
        <link rel="stylesheet" type="text/css" href="/styles/@common.css"/>
        <link rel="stylesheet" type="text/css" href="/styles/<?php echo APP_NAME ?>.css"/>
        <script type="text/javascript" src="/scripts/@common.js"><!-- --></script>
        <script type="text/javascript" src="/scripts/<?php echo APP_NAME ?>.js"><!-- --></script>
        ...

Si la logique de votre application diffère quelques peu en fonction de la version, vous avez 2 solutions :

  1. faire des switch(APP_NAME) dans la logique et coder les spécificités dans le même fichier
  2. externaliser les spécificités dans des fichiers distincts (de préférence des classes ;)), faire un include('features/'.APP_NAME.'.php'); au début de votre script et coder différentes versions de la fonction ou de la classe dans chacun des fichiers features/*.php

Si vous travaillez en objet, vous pouvez réaliser des interfaces que devront implémenter vos implémentations spécifiques de vos "features" et charger la bonne classe en faisant par exemple :

<?php

...
$featureClass = ucfirst(APP_NAME).'_Feature1Service';
require_once dirname(__FILE__).'/../classes/'.str_replace('_','/',$featureClass).'.php');
$feature = new $featureClass;

$result = $feature->laMethodeQuiMInteresse($leParam1,$leParam2);

...

Vous n'avez plus qu'à coder le fichier classes/Client1/Feature1Service.php :

<?php

class Client1_Feature1Service implements Feature1Interface {
    public function laMethodeQuiMInteresse($leParam1,$leParam2) {
        // votre code spécifique ici
        ...
    }
}

Si un nouveau client vous demande une version de votre application adapté à ses besoins, vous créez simplement ou nouveau virtual host Apache, un nouveau nom de code pour la version (ex: client2), un nouveau fichier de configuration et d'initialisation (configs/client2.php, inits/client2.php), des nouveaux fichiers CSS et JS (styles/client2.css, scripts/client2.js) et une nouvelle version de vos features spécifiques (classes/Client2/Feature1Service.php)

Ce type de méthode peut être mise en conjonction avec l'utilisation de frameworks comme Zend Framework, pensez à la variable d'environnement APP_NAME dans Apache !

Et vous quelles sont vos pratiques ?