Du Javascript dynamique dans une vue en utilisant sf_format

Il arrive que l’on ai besoin d’utiliser un script javascript spécifique dans une vue. Un script dynamique qui nécessite d’être renseigné par des informations de php (utiliser des variables ou des méthodes de nos objets).

Dans mon précédent post j’évoquais les différentes possibilités d’inclure le javascript dans les vues.

  • Mettre des balises <script> directement au milieu du html (un peu crade mais efficace)
  • Faire un fichier .js « en dur » dans le dossier /web/js (mais là on perd la possibilité d’utiliser du php)
  • Utiliser un slot dans le <head> du template
  • Utiliser une vue

C’est ce dernier point que je vous propose de voir aujourd’hui.

Pour se dessiner un petit background on va prendre l’exemple d’une vue index dans un module d’actualités.
Dans cette vue on veut faire un appel ajax sur un lien et on veut utiliser le routing pour définir l’url du script à appeler.

On va donc utiliser une action et deux vues, une pour la page html et une pour le javascript qui sera inclus dans la vue html. On utilise des sf_format différents.

On créé la route qui servira pour les deux vues (/app/frontend/config/routing.yml).

...
actu_index:
  url:   /actualites/index.:sf_format
  param: { module: actu, action: index, sf_format: html }
...

Dans notre action on récupère juste les dernières actualités à afficher dans la page html (/app/frontend/modules/actu/actions/actions.class.php).

<?php
 
class actuActions extends sfActions
{
 
  public function executeIndex(sfWebRequest $request)
  {
    $this->actus = Doctrine::getTable('Actu')->getLast();
  }
 
}

La vue Html. C’est la que ca se passe ! On fais un use_javascript() auquel on passe le url_for() de la même vue en spécifiant juste le sf_format à ‘js’ (/app/frontend/modules/actu/templates/indexSuccess.php).

<?php use_javascript(url_for('@actu_index?sf_format=js')) ?>
<div class="liste_actus">
  <?php foreach($actus as $actu): ?>
    <div class="actu">
      <h3><?php echo $actu->getTitre() ?></h3>
      <p><?php echo $actu->getTexteCourt() ?></p>
      <div class="action"><?php echo link_to('Lire la suite', '@actu_detail') ?><div>
    </div>
  <?php endforeach; ?>
</div>

Et donc la vue js sera inclue par la vue html qui rajoute dans le head l’appel au fichier.

<script type="text/javascript" src="/actualites/index.js"></script>

Il ne reste plus qu’a faire la script javascript dans la vue /app/frontend/modules/actu/templates/indexSuccess.js.php ou on peut avoir accès à tous les éléments de symfony que l’on désire.

Par exemple là un peut appel ajax en jQuery ou je récupère l’url du script appelé grâce au routing.

?View Code JAVASCRIPT
jQuery(function() {
 
  $('div.action a').click(function(event) {
    event.preventDefault();
    $.post(
      '<?php echo url_for('@actu_detail') ?>',
      { url: $(this).attr('href') },
      {},
      'script'
    );
  });
 
});

Il se peut que dans la vue javascript on n’ait pas besoin d’exécuter toute l’action.
Par exemple ici, dans ma vue javascript, je n’ai pas besoin des dernières actualités, il est donc possible de filtrer pour alléger l’action grâce au sf_format.

<?php
 
class actuActions extends sfActions
{
 
  public function executeIndex(sfWebRequest $request)
  {
    if($request->getParameter('sf_format') != 'js')
    {
      $this->actus = Doctrine::getTable('Actu')->getLast();
    }
  }
 
}

Après, libre a chacun de voir si on doit utiliser la même action que la vue html ou si la vue javascript nécessite sa propre action.

En utilisant une action séparée pour la vue javascript on peut s’amuser à pousser le vice du camouflage en utilisant un routing qui fasse croire que l’on appelle un fichier .js (Attention si jamais un fichier avec le même nom existe réellement dans le répertoire /web/js c’est ce dernier qui sera inclus).

...
actu_index_js:
  url:   /js/actu.:sf_format
  param: { module: actu, action: index, sf_format: js }
...

Avantage de cette technique :

  • Un code source html super « clean »

Inconvéniant :

  • Pour une page html, on fait deux appels à symfony.
    A utiliser avec parcimonie et bien optimiser les actions pour ne pas faire des requêtes inutiles sur la base de donnée.

Partagez cet article