[Admin generator] Paramètre ‘table method’

Une petite astuce que j’utilise depuis longtemps mais que je n’avais jamais pensé à partager : optimiser le nombre de requêtes Doctrine et par la même occasion, un module d’admin generator.

J’ai un module d’admin generator article lié au modèle Article.

  • schema.yml
Article:
  connection: doctrine
  actAs:
    Timestampable: ~
    Taggable: ~
    Sluggable:
      fields: [titre]
      name: slug
      type: string
      length: 255
      unique: true
      canUpdate: true
  columns:
    titre:
      type: string(255)
      notnull: true
    # et d'autres champs
    id_auteur:
      type: integer
      notnull: true
  relations:
    Auteur:  { class: vjGuardUserProfile, onDelete: SET NULL, onUpdate: CASCADE, local: id_auteur, foreign: id }
  • generator.yml
 list:
 title: Liste des articles
 display: [titre, date_publication, Auteur]
 max_per_page: 5
 table_method: retrieveBackend
  • ArticleTable.class.php
public function retrieveBackend(Doctrine_Query $q)
{
  $rootAlias = $q->getRootAlias($q);
  $q->leftJoin($rootAlias.'.Auteur au');
  return $q;
}

Dans cet exemple, je passe de 6 requêtes Doctrine pour l’affichage de 5 lignes à 3 requêtes.

Ce n’est pas énorme mais sur 20 lignes et 3 relations, on passe de 63 requêtes à

3 requêtes !

Sisi !

Alors, abusez-en !

Symfony Live 2010 coming !

Pas beaucoup de nouvelles ces derniers temps (cours du soir, examens, taf, blog en développement, …) mais ça va revenir !

Mais bon, ce n’est pas le propos du jour ! Non, aujourd’hui, je tenais juste à vous rappeler la tenue la semaine prochaine du Symfony Live 2010.
Cet événement, déjà très intéressant l’an dernier, risque de l’être encore plus cette année ! Ca va parler internationalisation, admin generator, Zend Framework ou encore Doctrine 2.0 mais surtout Symfony 2.0 ! Eh oui ! La première release de sf2 va être dévoilée mercredi 17 février !

Qui plus est, c’est l’occasion de rencontrer la communauté mais surtout la core team et de mesurer l’étendue de symfony à travers le monde.

Je vous conseille de ne pas manquer cet événement ! Il est encore possible de s’y inscrire donc, rendez-vous là-bas !

Conférence Symfony Live 2010

Une petite news juste pour rappeller (ou pour apprendre qui sait :p) que vous pouvez vous inscrire à la conférence Symfony Live 2010 qui se tiendra les 16 et 17 février 2010 à Paris (plus d’infos).
Sachez que cette conférence ne se tiendra pas en français mais en anglais !

De plus, il est prévu une journée d’entrainement sur symfony le 15 février (pas plus d’infos pour l’instant sur le contenu de l’entrainement).

Le programme de cette conférence est très intéressant :
- working with the admin generator
- playing with the symfony components
- Doctrine 2
- Symfony 2 revealed (présentation de l’utilisation de sf 2 et publication de la version alpha !)
- et bien d’autres

Cette conférence (bien qu’en anglais) semble vraiment dans le prolongement de la précédente et je suis sûr que l’ambiance sera aussi bonne que la première !

Qu’attendez-vous ? Allez vous inscrire !!!

Internationaliser le filtre ‘is_empty’ de l’admin generator

Quel développeur symfony ne s’est pas posé cette question : comment internationaliser le filtre ‘is_empty’ de l’admin generator ?

Vous trouverez plusieurs solutions sur le net mais il y en a une que j’apprécie fortement et je vais vous en faire profiter :
- ajoutez la fonction privée __($string) dans le fichier /path_du_projet/lib/filter/doctrine/BaseFormFilterDoctrine.class.php :

protected  function __($string) {
  sfProjectConfiguration::getActive()->loadHelpers(array('I18N'));
  return __($string, array(), 'sf_admin');
}

- dans chaque fichier des filtres de votre modèle (/path_du_projet/lib/filter/doctrine/ModelFormFilter.class.php) :

$this->widgetSchema['champ']->setOption('empty_label', $this->__('is empty'));

- ajoutez dans le fichier /path_du_projet/apps/votre_app/i18n/sf_admin.fr.xml (si vous n’utilisez pas ce fichier, n’hésitez pas à le récupérer dans le répertoire /path_de_symfony/plugins/sfDoctrinePlugin/i18n/sf_admin.fr.xml) :

<trans-unit>
 <source>is empty</source>
 <target>est vide</target>
</trans-unit>

Cette méthode fonctionne pour toutes les traductions nécessaires et peut servir un peu partout.

Retour & nouveau plugin : vjThemePlugin !

Bonjour ! Bonjour !
Me revoilà ! Après plusieurs semaines d’absence de mon blog pour quelques vacances et parce que c’est bientôt la rentrée, nous voilà reparti pour de nouvelles aventures :p

Pour commencer, rien de bien compliquer histoire de se remettre en jambe : un petit plugin de theme d’admin generator vjThemePlugin !

Je préfère préciser tout de suite, ce thème n’est pas une révolution, loin de là. Il se base sur le thème d’admin generator de Doctrine en lui ajoutant quelques petites choses :

  • pagination au dessus de la liste (ainsi qu’en dessous)
  • nom des colonnes (+ tri) en dessous de la liste (ainsi qu’au dessus)
  • les filtres ne sont plus affichés en colonnes sur le côté mais sont placés en ligne au dessus de la liste mais sont cachés en standard (un lien permet de les afficher puis de les recacher)

Pour préciser un peu les choses, voici trois screenshots :

  • liste avec pagination + colonnes + filtres cachés

  • liste avec pagination + colonnes + filtres affichés

  • liste de nombreux filtres

Ce petit plugin intègre de base les fichiers javascript jQuery, les deux icônes + et -, le thème complet de l’admin generator.

Une fois installé, il suffit de générer un module d’admin generator ou de modifier le thème d’un module existant.

Voili voilou ! Je vous laisse le tester directement pour vous faire une idée :)

Page du plugin sur le site officiel symfony
Guide d’installation et d’utilisation
Repository SVN : http://svn.symfony-project.com/plugins/vjThemePlugin/

Pour toutes questions, n’hésitez pas !

A bientôt pour de nouvelles aventures :)

Intégration de la librairie XAJAX (admin generator) – Partie 1

Suite à l’article publié la semaine dernière sur comment intégrer la librairie FPDF à symfony, je vais vous présenter aujourd’hui comment intégrer la librairie XAJAX.

Intégration de la librairie XAJAX
- téléchargez la dernière version de la librairie XJAX (page de téléchargement officielleversion 0.5 RC2 zip utilisée dans ce tutoriel)
- décompressez le fichier puis placez le répertoire xajax_core dans le répertoire lib/ de votre projet  ce qui doit donner : /path_du_projet/lib/xajax_core
- placez le répertoire xajax_js dans le répertoire /web de votre projet ce qui doit donner : /path_du_projet/web/xajax_js
- créez le fichier xajax_symfony.php dans /path_du_projet/lib/xajax_core/ :

<?php

class sf_xajax{
  static function getXajaxObj(){
    global $xajax_symfony;
    if (!isset($xajax_symfony)){
      if(sfConfig::get('sf_app')."_".sfConfig::get('sf_environment')==sfConfig::get('app_index_conf'))       $php_file="";
      else $php_file=sfConfig::get('sf_app')."_".sfConfig::get('sf_environment').".php/";
      $xajax_symfony = new xajax("/".$php_file."xajax");
    }
    return $xajax_symfony;
  }

  static function registerFunctions($functions){
    $xajax_symfony = sf_xajax::getXajaxObj();
    foreach($functions as $function){
      $xajax_symfony->register(XAJAX_FUNCTION,$function);
    }
  }

  static function processRequest(){
    $xajax_symfony = sf_xajax::getXajaxObj();
    $xajax_symfony->processRequest();
  }

  static function printJavascript(){
    $xajax_symfony = sf_xajax::getXajaxObj();
    $xajax_symfony->printJavascript("/");
  }
}
?>

- créez le fichier xajaxHelper.php dans /path_du_projet/lib/helper/ :

<?php

  function xajax_input($type,$value,$function,$event,$funcArgs,$tagParams){
    $tmpVal = "<input type=\"$type\" value=\"$value\"";
    $fArgs = join(",",$funcArgs);
    $tmpVal .= " $event=\"xajax_$function($fArgs)\"";
    foreach($tagParams as $pKey=>$pValue){
      $tmpVal .= " $pKey=\"$pValue\"";
    }
    $tmpVal .="/>";
    return $tmpVal;
  }

  function xajax_js_get_value($objId){
    return "xajax.$('$objId').value";
  }

  function include_xajax_javascript($uri){
    sf_xajax::printJavascript($uri);
  }

  function init_xajax_javascript(){
    sf_xajax::processRequest();
  }

  function register_functions($functions=array()){
    sf_xajax::registerFunctions($functions);
  }

  function xajax_start_form($id,$function,$tagParams){
    $tmpVal = "";
    foreach($tagParams as $pKey=>$pValue){
      $tmpVal .= " $pKey=\"$pValue\"";
    }
    return "<form id=\"$id\" action=\"javascript:void(null);\" onsubmit=\"xajax_$function(xajax.getFormValues('$id'));\"$tmpVal>";
  }

  function xajax_end_form(){
    return "</form>";
  }
?>

Intégration à l’admin generator
- en ligne de commande :

./symfony generate:module mon_application tools

- dans le fichier layout.php de votre application d’admin generator :
avant le doctype :

<?php use_helper('xajax') ?>
<?php init_xajax_javascript() ?>

entre les balises head :

<?php include_xajax_javascript() ?>

- dans le fichier routing.yml de votre application d’admin generator :

xajax:
  url:  /xajax
  param:  { module: tools, action : xajax }

Il nous reste à créer les actions dans le module tools et à utiliser ces actions dans d’autres modules.

Fin de la première partie. La suite demain !

Intégration de la librairie FPDF (admin generator)

Je vais vous présenter aujourd’hui comment intégrer la librairie FPDF à symfony et surtout, comment l’intégrer proprement dans une page web.

Intégration de la librairie FPDF
- téléchargez la dernière version de la librairie FPDF (page de téléchargement officielleversion 1.6 tgz utilisée dans ce tutoriel)
- décompressez le fichier dans le répertoire lib/ de votre projet (personnellement, j’ai créé un repertoire lib/tools/) ce qui doit donner : /path_du_projet/lib/fpdf16

Intégration à l’admin generator
- dans le fichier action.class.php de votre module d’admin generator :

public function executeMonPDF(sfWebRequest $request){
  // on définit le répertoire des polices (en dur ici mais il suffit de placer le paramètre dans le fichier app.yml)
  define('FPDF_FONTPATH','/path_du_projet/lib/tools/fpdf16/font/');
  // on charge la classe FPDF
  $this->pdf = new FPDF();
  // on ajoute une page au document
  $this->pdf->AddPage();
  // j'écris un texte en arial 11 gras sur fond blanc
  $this->pdf->SetFillColor(204,204,204);
  $this->pdf->SetFont("Arial",'B',11);
  $this->pdf->Write(5,'Mon premier document PDF sous symfony !');
  // nom du fichier pdf qui sera créé
  $this->file_name = "uploads/pdf/mon_pdf_sous_symfony.pdf";
  // on exporte le fichier
  $this->pdf->Output($this->file_name, "F");
  // on définit la classe du div contenant le PDF
  $this->classe = "pdf";
  // on donne un titre <h1> à la page
  $this->h1 = "Impression de mon premier PDF";
  // on appelle le template pdfSuccess.php
  $this->setTemplate('pdf');
}

- dans le fichier pdfSuccess.php de votre module d’admin generator :

<h1><?php echo $h1 ?></h1>
<div class="sf_admin_pdf">
  <object data="<?php echo $file ?>" type="text/html" codetype="application/pdf" class="object_pdf"></object>
<div>

- dans le fichier web/css/main.css du projet :

div.sf_admin_pdf{
  margin:0 auto;
  text-align:center;
  width:95%;
  height:80%;
  border:2px solid black;
}
.object_pdf{
  width:100%;
  height:100%;
}

- dans le fichier generator.yml de votre module d’admin generator :

object_actions:
  monpdf: { label: mon PDF , action: MonPDF }

Ces quatres fichiers devraient vous permettre d’intégrer un document PDF de cette manière :

Cela permet d’éviter d’avoir directement le document à télécharger (on peut le sauvegarder ou l’imprimer par exemple) ou de l’avoir en plein écran et de devoir faire Page précédente ou même de l’avoir dans une nouvelle fenêtre.

J’ai été beaucoup plus loin dans l’intégration de FPDF, j’ai créé une classe qui étend celle de FPDF qui me permet de gérer un en-tête et/ou un pied de page ou encore de créer des fonctions d’affichage différentes, etc …

Pour ce qui est de l’utilisation de FPDF, elle est assez simple et la documentation sur le site officiel (documentation + tutoriaux) est assez explicite. Si vous avez encore des soucis, d’autres tutoriaux sont disponibles par une simple recherche sur Internet.

Petite astuce, FPDF ne gère pas l’UTF-8, pensez donc à bien utiliser utf8_decode() au besoin :)

On se retrouve bientôt pour un tutoriel sur l’intégration de XAJAX !

Mon premier projet Symfony

Je viens tout juste de terminer mon premier projet complet sous symfony (17,5 jours) consistant en une reprise d’un outil métier pour la gestion des Déclarations d’Intention d’Aliéner (D.I.A.).

La déclaration d’intention d’aliéner (D.I.A.) est un imprimé CERFA destiné à tous les propriétaires, personne physique ou morale, désirant vendre leurs biens immobiliers par lequel, ils doivent obligatoirement informer la Ville de ce projet.

Il fallait donc un outil permettant d’insérer des fiches renseignant l’ensemble des informations du CERFA mais également de gérer les études notariales, les adresses de la ville et d’exporter au format SLK (pour des statistiques) ou PDF (impression de fiches & de courriers auto-générés).

Ce projet m’a permis d’appréhender symfony et d’y intégrer différentes technologies (AJAX, PDF, SLK, …).

L’essentiel du projet est basé sur l’admin generator.

Organigramme technique du projet


+ Afficher l’image en grand

Fonctionnalités spécifiques
- L’application backend est sécurisée grâce au module login basé sur l’authentification Active Directory.
- Intégration de la librairie PHP XAJAX (affichage automatique d’une liste déroulante de villes correspondant à un code postal, complétion de multiples champs en fonction d’un autre champ)
- Intégration d’un bloc PDF dans la page web

Désactiver les filtres

Récemment, j’ai souhaité désactiver les filtres dans certains modules de mon admin generator et impossible. J’ai passé un peu de temps sur le net et j’ai fini par trouver :

filter:
  class: false

Simple non ? Mais il fallait le savoir :)

Que peut-on mettre de spécial dans le fichier generator.yml ?

Allez, en route pour la première astuce !

Outre les paramètres standards sur lesquels je ne m’étendrai pas (Documentation officielle), je me suis rendu compte que certains paramètres supplémentaires n’étaient pas très explicites (surtout depuis les modifications de l’admin generator entre la 1.0 et la 1.1/1.2).  Je vais donc vous retranscrire ce que j’ai pu trouver lors de mes recherches :


- params est ignoré (paramètre utilisé en version 1.0)


- correspond au nom du champ qui sera affiché entre les balises label du formulaire

numero_dossier:  {label: Numéro }

- permet d’afficher une popup de confirmation

confirm: Etes-vous sûr de vouloir supprimer cette fiche ?

- récupère la valeur d’un champ dans le fichier app.yml

type:
  label: <?php echo sfConfig::get('app_label_type') ?>

- format de date

date_format: dd/MM/yyyy

- permet d’afficher un texte sous le champ de formulaire

help: "1 à 9 (voir plan)"

- attributs HTML qui seront appliqués au champ correspondant

attributes: { readonly: true, class: ma_classe }