10 novembre 2008
Après une première tentative peu concluante, voici un autre helper permettant de faire des liens entre différentes applications dans Symfony 1.2.
<?php
/**
* @author Olivier Mansour
*/
/**
* return an url for a given symfony application and an internal url
*
* @author Olivier Mansour
*
* @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')
{
$initial_app = sfContext::getInstance()->getConfiguration()->getApplication();
$initial_web_controler = basename(sfContext::getInstance()->getRequest()->getScriptName());
// 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); // usefull ?
unset($context);
//remove initial web controler
// genUrl use $this->context->getRequest()->getScriptName();, its a call to $_SERVER
// so I need this (sort of) hack
$script_name = $appname;
if (($env != 'prod') and $env)
{
$script_name.='_'.$env;
}
$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;
}
Pour l’utiliser, c’est à peu près comme url_for :
<?php echo cross_app_url_for('front' , 'module/action?id=5&tmp=ok#raoul'); ?>
<?php echo cross_app_url_for('front' , '@route'); ?>
Jusqu’ici ça marche (Symfony 1.2 est en cours de développement, l’API peut encore un peu changer, attention) ! N’hésitez pas à mettre un commentaire si vous avez un retour.
Dans Info et autres geekeries | 8 commentaires | Tags : cross app links > php > php5 > symfony > symfony 1.2
24 juillet 2008
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
<?php
/**
* @author Olivier Mansour
*/
/**
* return an url for a given symfony application and an internal url
* work with symfony 1.1
* freely inspired from sfWebControlleur code
*
* @author Olivier Mansour
*
* @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')
{
if (sfConfig::get('sf_no_script_name'))
{
// wont work
throw new sfException(__FUNCTION__.' : the cross app link helper will not work with sf_no_script_name to true');
}
// get the environment
if (is_null($env))
{
$env = sfContext::getInstance()->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
Dans Info et autres geekeries | 12 commentaires | Tags : cross app links > php5 > symfony > symfony 1.1