Liens inter-applications avec Symfony 1.1

Un important travail réalisé pour la sortie de Symfony 1.1 a été le retrait du pattern singleton du framework. On peut maintenant instancier plusieurs objet sfContext par exemple. Cela permet notamment de faire des liens inter-application a peu près proprement. Voici l’avancée de mon travail sur la question :

fichier lib/helper/crossAppLinkHelper.php

getConfiguration()->getEnvironment();
  }
    
  // context creation
  if (!sfContext::hasInstance($appname))
  {
    $c = ProjectConfiguration::getApplicationConfiguration($appname, $env, $debug);
    sfContext::createInstance($c, $appname);
  }
	
  list($route_name, $parameters) = sfContext::getInstance($appname)->getController()->convertUrlStringToParameters($url);
  $request = sfContext::getInstance($appname)->getRequest();
	
  $url_root = $request->getRelativeUrlRoot();
  if ($absolute)
  {
    $url_root = 'http'.($request->isSecure() ? 's' : '').'://'.$request->getHost().$url_root;
  }
	
  //scriptname
  $scriptname = '';
  if (($env != 'prod') and ($env))
  {
  	$env_suf = '_'.$env;
  } 
  else
  {
   $env_suf = '';
  }
  if (!file_exists(sfConfig::get('sf_web_dir').DIRECTORY_SEPARATOR.$appname.$env_suf.'.php'))
  {
  	//test with index ?
  	if (file_exists(sfConfig::get('sf_web_dir').DIRECTORY_SEPARATOR.'index'.$env_suf.'.php'))
  	  $scriptname = 'index'.$env_suf.'.php';
  	else
      throw new sfException(__FUNCTION__.' : can't find a script name for appname : '.$appname.' and env : '.$env); 	 
  }
  else
  {
  	$scriptname = $appname.$env_suf.'.php';
  }
	

  $fragment = '';
  // strip fragment
  if (false !== ($pos = strpos($url, '#')))
  {
    $fragment = substr($url, $pos + 1);
    $url = substr($url, 0, $pos);
  }
  
  // generate url
  list($route_name, $parameters) = sfContext::getInstance($appname)->getController()->convertUrlStringToParameters($url);
  
  if (sfConfig::get('sf_url_format') == 'PATH')
  {
    // use PATH format
    $divider = '/';
    $equals  = '/';
    $querydiv = '/';
  }
  else
  {
    // use GET format
    $divider = ini_get('arg_separator.output');
    $equals  = '=';
    $querydiv = '?';
  }
  $web_url = $url_root.$querydiv.$scriptname.sfContext::getInstance($appname)->getRouting()->generate($route_name, $parameters, $querydiv, $divider, $equals);
  
  if ($fragment)
  {
    $web_url .= '#'.$fragment;
  }
  
  return $web_url;
}

Pour l’utiliser (par exemple, depuis une application nommée back) :

< ?php echo cross_app_url_for('front' , '/module/action?id=5&tmp=ok#raoul'); ?>

Je ne l’ai pas beaucoup testé et a vrai dire je ne sais pas si on peut faire plus efficace. Le point particulier qui m’a poussé à écrire autant de code est que, si il est facile d’extraire les routes pour un contexte donnée, la méthode genUrl de sfWebController utilise un objet sfRequest pour obtenir l’url du contrôleur (back_dev.php par exemple) ce qui est bloquant dans mon cas.

Si vous avez des retours n’hésitez pas.

Vous pouvez télécharger le code cité plus haut : crossAppLinkHelper.php.zip

Publicités

12 réflexions au sujet de « Liens inter-applications avec Symfony 1.1 »

  1. nautilebleu

    http://fr.pastebin.ca/1082529

    Ce n’est pas un retour mais voici ma solution, pas très différente apparemment.
    Je ne gère dans ce helper que la génération du lien. Il faut donc faire:

    link_to(‘text’, cross_app_link_to(‘app’, ‘route’, array(
    ‘arg1’ => ‘value1’,
    ‘arg2’ => ‘value2’,
    )))

    Je ne gère pas non plus les fragments.

    A noter que certains paramètres de config (tels que ceux du sfPropelActAsNestedSetBehaviorPlugin disparaissent lorsque l’on switche le contexte, d’où le stockage de ces paramètres au début du helper.

    Répondre
  2. Tonio

    Hello,

    J’essaie de me servir de cette fonction. Si je génère une URL dans une action, aucun soucis. Par contre si je m’en sers dans layout.php, je perds mes feuilles de style (pas de d’appel dans le html généré). C’est possiblement un bug, ou j’ai encore codé avec les pieds ? 🙂

    Merci,

    Tonio

    Répondre
  3. Oncle Tom

    À noter que j’ai aussi découvert `sfContext::switchTo(‘controller_env’)` qui effectue une bascule totale du contexte vers cet environnement (config, utilisateurs & cie).

    Je l’ai utilisé dans le cas de liens « preview » du back vers le front sans avoir à me casser la tête.

    Très pratique je trouve.

    Répondre
  4. Oncle Tom

    Je pense que je rencontre le même problème que Tonio. Il se trouve qu’en faisant sfContext::createInstance(), symfony bascule automatiquement vers cette instance.

    Donc tu perds tes styles et tout parce qu’il écrase également tout le travail qui a été fait jusqu’à présent (css, js, entêtes http & cie).

    Je m’en suis rendu compte : mes partials ne s’affichaient plus après l’utilisation du helper. symfony allait les chercher dans le frontend.

    Il faudrait rajouter une bascule vers l’instance de départ pour rétablir la vapeur comme il faut.

    Répondre
  5. Olivier Mansour

    Merci Thomas et Tonio pour vos retours, il y a un bien un os. A priori pour restaurer le contexte de base il suffirait :

    le sauver au début de la fonction
    $context = sfContext::getInstance();

    ou sauver simplement la configuration
    $fconfiguration = sfContext::getInstance()->getConfiguration()

    et switcher vers lui avant le return avec sfContext::switchTo ou encore le recréer depus la config.

    Je n’ai pas testé, mais si quelqu’un a une bonne solution sous le coude, cela m’enchanterai 😉

    Répondre
  6. Thomas

    Hi Olivier!

    Thanks for your code – two little things I have discovered:

    1) You do

    list($route_name, $parameters) = sfContext::getInstance($appname)->getController()->convertUrlStringToParameters($url);

    twice, while you don’t even use the result(s) of the first call

    2) The URL generation won’t work with more complex URLs which do not follow the /:module/:action pattern, because convertUrlStringToParameters() is not aware of these patterns. Its better to use

    $parameters = sfContext::getInstance($appname)->getRouting()->parse($url);

    and give null as first parameter to sfRouting::generate() later on.

    Thomas.

    Répondre
  7. Olivier Mansour

    thanks for those notes. Merci pour vos remarques.

    Pour l’instant je n’en ai pas le temps mais je pense que l’on peut fournir une bonne solution rapidement.

    I’ll try to find out something working fine with sf 1.2 quickqly.

    regards
    Olivier

    Répondre
  8. Ping : Liens inter-applications avec Symfony 1.2 » Glagla Dot Org - Le blog sans prétentions d’Olivier Mansour

  9. John Kary

    Oliver,
    A very strange problem using Symfony 1.1.5 and this helper function.

    If I try using your helper function, all of my stylesheets except the debug main.css are stripped from my layout.php:

    //Used when inside an app called ‘admin’

    The code creating the problem in your helper function is Line 39. After Line 39 executes the CSS files are removed:
    sfContext::createInstance($c, $appname);

    Any idea what is wrong?

    Répondre
  10. John Kary

    Sorry, the code I am using to call the helper is this:
    //Used when inside an app called `admin`
    <?php echo cross_app_url_for(‘backend’,’default/index’); ?>

    Répondre

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s