====== Etude perso ====== ===== Multi-sites avec héritage ===== Dans un site on doit pouvoir surcharger : assets, action, view, model, lib, DSN, Config: Pour des classes qui porteraient le même nom mais seraient dans différents sites : Quid du cache de l'op-code ?? > 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. > A filter **subdomainFilter** > http://forum.symfony-project.org/index.php/m/80813/ > [[http://mirmodynamics.com/tag/howto|Multiple domains for one symfony project, the basics, config file version]] > [[http://mirmodynamics.com/post/2008/12/22/Multiple-domains-for-one-symfony-project%2C-the-basics|Multiple domains for one symfony project, the basics]] 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 : * AssetHelper::javascript_path(...) * AssetHelper::stylesheet_path(...) * AssetHelper::image_path(...) * sfCommonFilter->execute * AssetHelper::get_stylesheets() * AssetHelper::stylesheet_tag() * AssetHelper::stylesheet_path(...) ==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 * AssetHelper::stylesheet_tag(). * AssetHelper::javascript_tag(). * AssetHelper::image_tag(). **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. [[http://www.symfony-zone.com/wordpress/2008/12/13/use-routing-to-server-localized-and-dynamic-javascript/|Use routing to serve localized and dynamic JavaScript]] Voir doc et code source: * [[http://www.symfony-project.org/api/1_2/AssetHelper#method_use_dynamic_stylesheet|AssetHelper->use_dynamic_stylesheet()]] [[http://trac.symfony-project.org/browser/tags/RELEASE_1_2_7/lib/helper/AssetHelper.php#L600|source code]] [[http://trac.symfony-project.org/browser/tags/RELEASE_1_2_7/test/unit/helper/AssetHelperTest.php#L209|unit test]] * [[http://www.symfony-project.org/api/1_2/AssetHelper#method_use_dynamic_javascript|AssetHelper->use_dynamic_javascript()]] [[http://trac.symfony-project.org/browser/tags/RELEASE_1_2_7/lib/helper/AssetHelper.php#L585|source code]] [[http://trac.symfony-project.org/browser/tags/RELEASE_1_2_7/test/unit/helper/AssetHelperTest.php#L201|unit test]] ====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()... {{:informatique:php:symfony:multisitescontroller.php.txt|Copie du multiSitesController}} 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(...) ====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. {{:informatique:php:symfony:multisitesfilter.class.php.txt|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. Par contre :\\ Certains models doivent pouvoir utiliser telles ou telles BdD (emargement, urne, autre...) ====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 : * [[http://groups.google.fr/group/symfony-devs/browse_thread/thread/9e7a266dccee3923| Couple of asset ideas for core]] (symfony developers 2008-07-28) ===== 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 [[http://groups.google.com/group/symfony-devs/browse_thread/thread/a85ff68f54d677edA Peut être une solution: [[http://snippets.symfony-project.org/snippet/342|A task to extract i18n labels from a form]]