Pouvoir retrouver des liens entre applications avec Symfony1

De e-glop
Révision datée du 13 juin 2013 à 14:21 par BeTa (discussion | contributions) (Limitations et mises en garde)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)

Problématique

Vous avez bâti une application web modulaire, se déclinant en plusieurs "applications Symfony1". Cependant, vos différents modules sont amenés à s'utiliser les uns les autres, à se connecter via des liens ou des appels Ajax par exemple... et vous n'avez aucun moyen dans Symfony1 pour créer des liens inter-applications.

Voyons ce que nous pouvons faire pour y remédier...

Solution

Nous allons donc chercher une solution pour créer des liens cross-applications. Nous allons donc créer un nouveau helper s'inspirant du UrlHelper, et nous allons l'appeler CrossAppUrlHelper :

// lib/helper/CrossAppUrlHelper.php

<?php
/**
 * @author Olivier Mansour
 * @author Baptiste Simon
 * @author Libre Informatique [1]
 */

/**
 * return an url for a given symfony application and an internal url
 *
 * @author Olivier Mansour
 * @author Baptiste Simon
 * @author Libre Informatique [2]
 *
 * @param string $appname
 * @param string $url
 * @param boolean $absolute
 * @param string $env
 * @param boolean $debug
 * @return string
 */
function cross_app_url_for($appname, $url, $absolute = false, $env = null, $debug = false)
{
  global $user;
  $user = sfContext::getInstance()->getUser();
  
  $initial_app = sfContext::getInstance()->getConfiguration()->getApplication();
  $initial_web_controler = basename(sfContext::getInstance()->getRequest()->getScriptName());
  $initial_config = sfConfig::getAll();
  // get the environment
  if (is_null($env))
  {
    $env = sfContext::getInstance()->getConfiguration()->getEnvironment();
  }
  
  // context creation
  if (!sfContext::hasInstance($appname))
  {
    $context = sfContext::createInstance(ProjectConfiguration::getApplicationConfiguration($appname, $env,  $debug), $appname);
  }
  else
  {
    $context = sfContext::getInstance($appname);
  }
  $web_url = $context->getController()->genUrl($url, $absolute);
  sfContext::switchTo($initial_app);
  sfConfig::add($initial_config);
  unset($context);

  //remove initial web controler
  // genUrl use $this->context->getRequest()->getScriptName();, its a call to $_SERVER
  // so starting the shameless part !
  $script_name = $appname;
  if (($env != 'prod') and $env)
  {
    $script_name.='_'.$env;
  }
  elseif ($script_name == "frontend")
  {
    $script_name="index";
  }
  $script_name.='.php';
  // check if this file exist
  if (!file_exists(sfConfig::get('sf_web_dir').DIRECTORY_SEPARATOR.$script_name))
    throw new sfException('can t find '.$script_name.' in the web directory');
  $web_url = str_replace ($initial_web_controler, $script_name, $web_url);

  return $web_url;
}

function cross_app_link_to($text, $appname, $url, $absolute = false, $env = null, $debug = false, $params = )
{
  return '<a href="'.cross_app_url_for($appname, $url, $absolute, $env, $debug).'" '.$params.'>'.$text.'</a>';
}

Cette solution est relativement pratique et s'utilise de manière assez similaire à ce que peut proposer le UrlHelper originel.

Nous l'avons adaptée de la proposition d'Olivier Mansour en l'optimisant afin d'éviter la multiplication des requêtes et des constructions d'environnements.

Limitations et mises en garde

Par contre, attention : chaque reconstruction d'environnement pour une application différente reparamètre la variable de configuration sf_csrf_secret, entraînant automatiquement le risque de la levée d'une exception dans vos formulaires, en particulier ceux issus des modules doctrine:generate-admin lors des actions de leur liste.

Deux solutions à cela :

  • soit vous paramétrez chacune de vos applications Symfony1 avec la même clé csrf_secret dans votre fichier app/*/config/settings.yml
  • soit vous devrez préciser, afin d'être certain d'éviter les bugs, une clé secrète pour chacun de vos sfForm utilisant la protection contre les attaques CSRF.

Crédits

Nous nous sommes inspirés dans cette solution de différents articles trouvés sur la toile, et en particulier de la solution d'Olivier Mansour. Cela datant de plusieurs années, nous n'avons pas fait l'effort de retrouver les liens correspondant, pardonnez-nous. Afin d'être cités dans cet article, comme il nous semblerait naturel le faire, n'hésitez pas à nous contacter pour ce faire : beta_AT_e-glop_DOT_net !