Table des matières

Etude perso

Multi-sites avec héritage

Dans un site on doit pouvoir surcharger : assets, action, view, model, lib, DSN, Config:

<note important>Pour des classes qui porteraient le même nom mais seraient dans différents sites : Quid du cache de l'op-code ??</note>

From there, all you need is a filter, or maybe a preExecute() section in your action (or parent action) to analyse the URI and to read something from your DB or your FS depending on that value. The URI can be pulled out of the sfRequest instance, or failing that just use PHP environment vars.

Comment stocker le siteId dans la sfConfig ou sfContext ?

Surcharge Asset(s)

javascript, css, images, …

Surcharge selon le siteId

AssetHelper::_compute_public_path(…) utilise $request→getRelativeUrlRoot() pour calculer la base du chemin.
Peut-on hacker ce RelativeUrlRoot() ? Bof, ce hack n'est pas suffisant puisque le fichier dans le siteId est optionel, il faut donc chercher le fichier au 2 endroits.

AssetHelper::_compute_public_path(…) est utilisé par :

3 solutions possibles

1) En fait tout ce boulot est initié dans sfCommonFilter, qui ne fait que ça d'ailleurs.
Il suffit donc de remplacer ce Filter par le notre, et y ajouter les méthodes remplaçant

2) Ou bien c'est à la charge de l'intégrateur de faire le bon lien (/site/$siteId/main.css) mais c'est dommage, et puis si l'on ne veut pas surcharger le template mais seulement le css ça ne fonctionne plus, pareils pour du javascript.

3) Ou encore créer des Helpers genre use_multiSites_stylesheet, use_multiSites_javascript, …

Dynamic JS & CSS

Et on voudrait aussi pouvoir modifier du javascript, du css dynamiquement.

Use routing to serve localized and dynamic JavaScript

Voir doc et code source:

Surcharge Action(s)

Pour les actions c'est la meme chose que pour les views (sf_module_dirs) sauf que dans un Filter c'est trop tard. Effectivement, Symfony construit l'action avant la chaîne de filtres.

Du coup j'ai déplacé le code du multiSitesFilter dans le multiSitesController avant l'appel à dispatch()…

Copie du multiSitesController

<note>TODO Avec cette technique c'est la classe sfAction toute entière que l'on surcharge, au lieu de simplement certaines actions… Il me semble avoir lu dans la doc que l'on pouvait découper les actions dans des fichiers individuels et voir aussi sfController→controllerExists(…)</note>

Surcharge View(s)

Besoin, contrainte

Permettre de surcharger les vues dans un site. Si le site ne surcharge pas la vue, alors celle située dans l'application qui est utilisée.

Le faire pour les vues des modules et aussi pour l'application (layout.php).

Solution

Bon, j'ai essayé pas mal de chose, mais il manquait toujours une données… Par exemple dans le filter il n'y a pas le viewName. En gros toutes les données ne sont pas calculées avant d'être dans les classes de View, par exemple il y a aussi le format de sortie qui influ sur le nom du fichier de template.

http://forum.symfony-project.org/index.php/m/81149/#msg_81149

Du coup, il faut plutôt agir sur la configuration.

Une copie du multiSitesFilter

Pour les modules (templates)

J'ai trouvé sfApplicationConfiguration→getTemplateDirs($moduleName) qui construit un tableau avec plein de chemin pour les templates. En 1er il regarde dans la config “sf_module_dirs”.

Du coup, j'ai ajouté le sfFilter “multiSitesFilter” qui calcule le chemin de l'éventuel template pour le siteId demandé, et hop !

Pour l'application (layout/decorators)

La Symfony est moins souple, il n'y a pas de tableaux.

Si un site est défini et qu'il contient un folder app/template alors remplacement de la config 'sf_app_template_dir'.

Comment propager le siteId dans les views ?

Les “Templates Shortcuts” de SF ($sf_context, $sf_user, …) sont rendus disponibles dans les vues au travers du système d'events. Dans sfViewParameterHolder→toArray() il y a firing de l'event 'template.filter_parameters'. sfContext est abonné à cet event (voir sfContext→initialize()) et y répond via sa méthode filterTemplateParameters(…).

Du coup je fais pareils : dans multiSitesController→dispatch() je l'abonne

  sfContext::getInstance()->getEventDispatcher()->connect('template.filter_parameters', array($this, 'getSiteId'));

et la callback getSiteId(…) fournira l'information :

  public function getSiteId(sfEvent $event, $parameters)
  {
    $parameters['siteId'] = $this->siteId;
    return $parameters;
  }

Surcharge Model(s)

Un peu complexe: les classes des modèles sont liées au schéma de données.

Dans le cas où il suffit d'ajouter des méthodes, c'est simple, il suffit de créer une classe héritière du model de base. Et ajouter dans l'autoload le chemin des modèles pour le site_id.

Par contre s'il y a changement du schéma … ???? - Regénération code ORM dans folder du site ?

Surcharge lib(s)

Aucun intérêt de surcharger une librairie.

On doit juste ajouter à l'autoloader le répertoire de librairies sur site en cours.

Surcharge DSN

Pas besoin de surcharge pour la config de base.

Par contre pour la configuration du site et les données, un site à son ou ses propres DSN. Ou bien toutes les tables doivents avoir un lien avec le site_id, ce qui me semble bien compliqué.

Il faut mieux étudier le schéma pour voir ce qui est commun et ne l'ai pas.

<note important> Par contre :
Certains models doivent pouvoir utiliser telles ou telles BdD (emargement, urne, autre…) </note>

Surcharge Config(s)

La surcharge de config doit fonctionner comme dans Symfony avec juste un level supplémentaire et dynamique : le site_id.

Je ne sais pas si ça va être possible…

Performance and Optimisation

CSS et Javascript

Read :

Internationalisation i18n

Form problem ?

As far as I know, the i18n:extract still doesn't extract strings for translation inside of the form classes. This is a real limitation for large projects with a lot of different languages.
look at A task to extract i18n labels from a form