Archives pour 'symfony'

Liens inter-applications avec Symfony 1.1

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

PHPTeam, une vieille application de retour sous Symfony

9 juillet 2008

Je découvre la nouvelle version de PHPTeam. Pour l’instant, le fork de Symfonians est encore un peu brutal, comme, par exemple, le bloc « a propos » mais il y a déjà quelques articles, un super logo et deux offres d’emploi !

Une bonne initiative si elle est suivie d’inscriptions et de contenus.

Bon courage aux développeurs de ce site.

L’architecture de Symfony 1.1

23 juin 2008

Un article sur le blog de Symfony présente brillamment la nouvelle architecture de Symfony.

Entre les lignes on devine le travail qui a été fait pour rendre les classes du framework indépendantes, ceci permettant la dissociation entre la « plateforme » et le « framework ».

Histoire d’alimenter le troll, si la version finale de Symfony tient ses promesses (pas de raisons … on en est à la seconde RC), la plupart des arguments en faveur du Zend Framework en réponse à ce billet, ne seront plus trop valables. A savoir, Symfony offrira la plus grande souplesse d’utilisation possible comme :

  • l’intégration des classes de la plateforme dans vos développement spécifiques,
  • la modification de toutes les conventions du framework,
  • le mélange avec d’autres frameworks de tout type.

\o/

Configuration SVN pour un projet Symfony

19 juin 2008

(post limite pense bête)

Voici la configuration SVN que j’utilise pour un projet Symfony 1.0 :

/
  svn:ignore
    .*
/cache
  svn:ignore
    *
/config
  svn:ignore
    databases.yml
    propel.ini
    generated-*
/data
  svn:externals
    symfony http://svn.symfony-project.com/tags/RELEASE_1_0_16/data/
/data/sql
  svn:ignore
    lib.model.schema.sql
    sqldb.map
/lib
  svn:externals
    symfony http://svn.symfony-project.com/tags/RELEASE_1_0_16/lib/
/lib/model
  svn:ignore
    map
    om
/log
  svn:ignore
    *
/plugins
  svn:externals
    sfJqueryPlugin http://svn.symfony-project.com/plugins/sfJqueryPlugin
/web
  svn:externals
    sf http://svn.symfony-project.com/tags/RELEASE_1_0_16/data/web/sf/
/web/uploads
  svn:ignore
    *

Pour les plugins bien sur, on ajoute ceux que l’on veut. Si on ne commite pas databases.yml et propel.ini, en général on commite des copies nommées databases.yml-dist et propel.ini-dist histoire de faciliter la vie des développeurs.

Vous voyez d’autres points ?

Symfony : comment gérer l’apparition du panneau de connexion dans les zones rafraichies en Ajax

27 mai 2008

Symfony permet assez facilement de mettre en œuvre des appels Ajax afin de dynamiser vos écrans. Symfony permet également de facilement sécuriser tout ou partie de vos applications via de simples paramétrages. Si l’utilisateur connecté n’a pas le degré suffisant d’autorisation ou si sa session a expirée, il sera automatiquement dirigé, par le filtre de sécurité de Symfony, vers, par exemple, le panneau de login de votre application.

Un effet de bord de ces techniques est que, si l’utilisateur de votre application laisse sa session expirer, puis lance une action Ajax devant rafraichir une partie de son écran, il verra le panneau de connexion apparaitre dans cette zone : effet peu ergonomique garanti !

Voila la technique que j’utilise pour pallier à ce problème. A vrai dire, je ne sais pas si elle correspond à l’état de l’art, mais elle a l’avantage de bien fonctionner sans nécessiter de multiples interventions dans l’application.

1/ Permettre l’évaluation du Javascript dans les templates affichés via des appels AJax

Cela dépend de la librairie Javascript que vous utilisez. Par exemple, avec JQuery, il faudra préciser que le type de donnée retourné est ‘html’. Si vous utilisez les helpers Symfony, il vous faudra ajouter 'script' => true au tableau d’options passé au helper.

Cette étape n’est pas obligatoire. Elle permet toutefois de rediriger les utilisateurs en Javascript vers le panneau de connexion.


2/ Modifier le code du contrôleur gérant votre panneau de connexion

On va simplement lui dire que, si il est appelé via une requête Ajax, il n’utilise pas la vue habituelle.

Par exemple :

  /**
   * Executes login action
   *
   */
  public function executeLogin()
  {
    if($this->getRequest()->isXmlHttpRequest()) {
      $this->getResponse()->setStatusCode(401);
      return 'redirect';
    }
    /*
    end of the login action code
   */
  }

3/ Créer la vue appelée précédemment

Ici le fichier loginRedirect.php

<?php
use_helper('Url');
echo javascript_tag ('
location.href=\'.url_for('@user_logout').'\';
');
?>

La route correspondant à l’action de déconnexion @user_logout doit bien sur exister.

Voilà !

Et vous, que pensez vous de cette méthode ?

Check-list du démarrage d’un projet Symfony

22 mai 2008

Voici une liste de petites choses que je fais systématiquement lors du démarrage d’un projet Symfony. J’espère que cela vous sera utile.

  • conception de base : applications, modules, choix des plugins (symfony propose un grand nombre de plugins souvent d’excellente qualité, c’est un point fort du framework),
  • branchement des librairies symfony sur les répertoires lib et data via des externals svn,
  • branchement des plugins choisis sur le répertoire plugins via des externals svn,
  • choix des environnements possibles pour l’application (dev et prod viennent par défaut, l’environnement de test peut être utile pour des projets nécessitant une configuration dédiée aux tests),
  • mise en place des contrôleurs pour chaque couple application/environnement,
  • revue de la configuration pour chaque application (fichier settings.yml : escaping_strategy, etag, standard_helpers, i18n, error_reporting …)

Certains détails me semblent très importants au démarrage du projet :

  • l’escaping strategy choisi conditionne la façon dont vous allez traiter certaines de vos variables dans le code de vos templates (par exemple, les fonctions du genre is_array ne marcheront plus car vos tableaux seront des objets sfOutputEscaperArrayDecorator, de même pour les objets qui ne seront plus de la même classe). Un changement dans cette variable de configuration peut donc affecter fortement le budget de votre projet … autant être sûr du premier coup.
  • Utiliser judicieusement la directive svn:ignore afin d’éviter de commiter les fichiers indésirables ou générer par symfony (comme le cache, les classes générées par propel, les contrôleurs de dev, les logs …).
  • La configuration du fichier php.yml permettant de contrôler l’environnement de votre future application est, selon moi, un moyen simple et pratique afin d’être sûr que tout le monde travaille dans la même configuration.

Si vous avez d’autres points de ce genre, n’hésitez pas à m’en faire part.

Frameworks php pour l’entreprise

16 mai 2008

Un peu de pub pour un livre blanc Clever Age auquel j’ai contribué.

Les frameworks suivants sont abordés : CakePHP, CodeIgniter, Symfony, Zend Framewok. Avec en fin de chaque chapitre un court paragraphe indiquant dans quels cas métier utiliser ce framework et, en fin de document, un magnifique tableau QSOS permettant leur comparaison aisée.

Symfony sans virtual host

26 avril 2008

Je vois dans mes stats qu’un internaute est tombé sur mon site en cherchant dans google : « symfony sans virtualhost ». Je vois bien son problème, toutefois, je ne donne pas cette astuce.

Pour me faire pardonner, la voici donc.

En fait, un problème survient si vous utilisez le générateur d’admin avec le thème par défaut ou bien la barre de débogage Symfony (en mode dev par exemple), symfony va faire appel a des fichiers javascripts ou css qu’il espère trouver dans un répertoire nommé /sf/.

Voila pourquoi la documentation de symfony vous propose de créer un virtual host avec un alias pointant vers ce fameux répertoire.

Pour un développeur, qui instancie un projet symfony sur son poste de travail, cette pratique n’est pas vraiment obligatoire.

Il faut tout d’abord trouver où sont les fichiers sur votre disque qui doivent apparaitre sous /sf.

Dans le cas d’une installation via PEAR ils seront sous PEAR_INSTALL_DIR/data/symfony/web/sf/. Si vous êtes sous Mac et que vous utilisez les binaires fournis par entropy.ch (voir ce post pour plus d’infos) cela doit donner un chemin comme ça :
/usr/local/php5/lib/php/data/symfony/web/sf/

Si vous utilisez un external svn pour installer symfony, en liant le dépot svn au répertoire data/symfony, les fichiers seront sous data/symfony/data/web/sf.

Ceci fait, deux choix rapides s’offrent à vous :

  1. copier brutalement le répertoire sf sous le dossier web,
  2. faire un lien symbolique (si votre OS le permet) dans le dossier web comme ça :

ln -s /usr/local/php5/lib/php/data/symfony/web/sf/ web/sf

(votre serveur Apache doit être configuré pour suivre les liens symboliques)

et voila.

ps : avec une sandbox ou un projet freezé, vous n’aurez pas ce souci, les fichiers étant copiés dans le répertoire web.

Propel : afficher la dernière requête effectuée

10 mars 2008
echo Propel::getConnection()->getLastExecutedQuery();

Certes la barre de débogage de symfony peut vous renseigner. Mais avec 7200 requêtes dans votre page vous êtes bien content de pouvoir générer une trace spécifique ;-) (à afficher ou écrire dans un log).

via prendre un Snippet.

Le futur langage incontournable du web : le javascript

9 mars 2008

Il y a quelques années, certains visionnaires me disaient : « Le javascript est l’avenir du web ». A l’époque je restais sceptique. Tout a bien changé avec la popularisation d’Ajax et finalement, plus aucun développeur web ne peut aujourd’hui se passer d’un zeste de Javascript dans la liste de ses compétences.

Mais franchement, j’ai découvert récemment ExtJS et je trouve les démonstrations tellement convaincante que je me dis moi aussi que voici le Java Swing du web ! (screencasts, démonstrations).

remarque : pour les programmeurs Symfony, il existe un plugin permettant d’intégrer ExtJS dans vos projets.