Toute l'actualité francophone sur PHP en un seul flux

Avril 2007 – Afup: La communauté francophone du Zend Framework se dévoile

Le Zend Framework est en phase terminale de développement, et une RC est prévue d'ici à la mi-mai. La communauté francophone autour de cet outil de développement PHP fait déja parler d'elle.
Philippe Le Van, Rodolphe Eveilleau (AFUP) et Julien Pauli ( moi-même, AFUP ) venons de lancer notre projet de centralisation de ressources humaines et techniques, francophones, autour du Zend Framework.
Le site portail http://www.z-f.fr a en effet pour but de rassembler les professionnels de l'outils. Muni d'un (...)

Avril 2007 – Dur Comme Faire: PHP 4 : La fin est proche

Derick Rethans vient d'annoncer officiellement la mort programmée de la version 4 de PHP. Ce sera pour la fin de cette année et c'est une excellente nouvelle ! PHP 5 est un très bel outil qui souffre beaucoup de l'inertie due au fait que PHP 4 est toujours maintenu (et surtout du manque de...

Avril 2007 – Prendre un Café: Mettez vous à PHP5. Vite.

[Via Nexen]

La meilleure nouvelle de la semaine (si c'est pas un poisson) :

PHP4 ne sera plus supporté officiellement à compter du 1er janvier 2008.

Autant vous dire qu'il va falloir se mettre à la version 5, et fissa. C'est une excellente nouvelle au vu des nombreux apports fonctionnels et structurels de cette mouture du langage, que je ne vais pas lister ici, d'autres l'ayant fait avant moi.

Edit du 13/07 : C'est désormais officiel :)

Avril 2007 – Afup: Statistiques PHP / Mars 2007

Les statistiques de diffusion PHP dans le monde pour mars 2007 sont arrivées. PHP 5 continue sa percée.

Avril 2007 – Dur Comme Faire: Précisions sur la certification Zend PHP

Suite à mon billet sur le passage de la certification Zend PHP, j'ai reçu quelques demandes de précisions. La question qui sembler tarauder le plus les candidats à cette certification est celle de sa difficulté et de son corollaire : comment savoir si on est prêt. Avant de poursuivre,...

Avril 2007 – tigrou/pwet.fr: Mairie-Coligny.fr, 5 ans après

Je viens de remettre le nez dans le site de mon village natal, Coligny , pour y supprimer le livre d'or qui était devenu au fil des années juste bon à stocker du spam... Je l'ai réalisé il y a presque 5 ans pendant un job d'été, à l'époque je venais de finir la première année de l'ENSSAT , je n'avais alors aucune idée de ce qu'était un CMS ni un framework de développement même si j'utilisais PHP depuis déjà quelques années. La mise en page est faite à partir de tableaux imbriqués, elle est d'ailleurs foireuse. Le code PHP derrière est tout aussi foireux, je me demande même comment certaines portions fonctionnent encore... À l'occasion il faudrait que je donne un vrai coup de peinture à ce site qui ne reflète pas l'esprit et le charme de ce petit village entre Bresse et Revermont .

Avril 2007 – Digital Fashion: Débuter avec le Zend Framework

Pour info.

Je suis un peu triste parce que je voulais m'atteler à cette tâche, mais bon il faut croire que j'ai trop lambiné :)

Avril 2007 – PHP Québec: Appel aux conférenciers

L'équipe de PHP Québec est présentement à la recherche de conférenciers désirant partager leurs expériences lors des rencontres mensuelles à Québec ainsi que Montréal.

Les présentations comportent un volet technique axé sur les librairies, extensions, techniques de développement ainsi qu'un volet affaires orienté sur les solutions clés en main, l'efficacité des processus, gestions de projets, etc. Les présentations doivent durée environ 1 heure et peuvent être en français ou en anglais.

Voici quelque thèmes de présentations:
  • Programmation orienté objets avec PHP5
  • Introduction à PHP5
  • Migration de PHP4 à PHP5
  • Les designs partners
  • Ajax et le développement d'applications riches
  • Les services web (Soap,Rest,xmlRPC)
  • Gestions de flux XML avec SimpleXml, Dom, XSL, ...
  • Gestions de permissions avec LDAP et PHP
  • Développement d'applications graphique avec PHP GTK ou NCurse
  • Optimisations d'applications
  • Traitement d'image avec GD et Imagik
  • Création de PDF avec PDFLib ou XML-FO
  • Sécuriser vos applications PHP
  • Introduction à PHP
  • Gestions de données avec MySQL, PGSQL, Oracle, DB2, ...
    Gestions de projets
  • La gestion du risque
  • Les CMS (Typo3,Joomla,TikiWiki, ...)
  • Les Framework et composants (Zend Framework,eZ Components,Cake,Symfonie, Dojo, ...)



Vous maîtrisez l'un de ces sujets ou un autre tout aussi pertinent? Vous avez un sujet de présentations à suggérer? Faites nous parvenir vos propositions et commentaires à board@phpquebec.com.

Les prochaines rencontres, à Québec, auront lieu les :
  • 14 mai
  • 11 juin
  • 9 juillet


Les prochaines, rencontres à Montréal, auront lieu les :
  • 3 mai
  • 7 juin
  • 5 juillet
  • 6 septembre
  • 4 octobre


Veuillez consulter notre calendrier des événements pour plus de détails.

Au plaisir de vous y voir.
L'équipe de PHP Québec

Avril 2007 – CreaOne: Svn pour les nuls

Svn successeur de Cvs, est une gestionnaire de version. Comme son nom l'indique, il permet de gérer les différentes versions d'un projet ou plus précisement chaque version d'un fichier. Il est souvent employé pour maintenir le code source d'un projet ou de la documentation d'un logiciel. Ayant (...)

Avril 2007 – Prendre un Café: Gagnez du temps avec Symfony 1.0 et son générateur de back-office

Lors du dernier petit-déjeuner Clever Age que j'ai animé sur les frameworks PHP, j'ai effectué une démonstration des fonctionnalités de génération de back-office existantes dans Symfony : la plupart des gens présents - pour la plupart découvrant la notion même de framework - ont été très impressionnés par la facilité déconcertante avec laquelle il était possible de développer une application complète en très peu de temps et d'étapes techniques grâce au générateur d'admin...

Personnellement, je suis tellement habitué à travailler avec de tels outils désormais que j'oublie parfois comme la vie est plus difficile sans eux... Je vais donc faire une démonstration afin que chacun puisse se faire son idée, sur sa propre machine :)

Pour faire très original, on va créer une petite application sommaire de gestion de weblog, doté des fonctionnalités suivantes :

  • Un auteur par billet
  • Billets multi-catégoriques (on pourrait aussi parler de tags)
  • Commentaires pour chaque billet

L'avantage est que la plupart des frameworks web proposent ce type de tutoriaux, donc ainsi vous pourrez plus aisément comparer :)

Installation de Symfony

Je vous renvoie à la documentation officielle ou à ce tutoriel pour installer Symfony sur votre machine et configurer un vhost apache pour votre nouveau projet. On partira sur la version 1.0.2, soit la dernière version stable disponible à l'heure où sont écrites ces quelques lignes.

Création d'un nouveau projet

Imaginons que votre projet soit créé dans /var/www :

$ sudo -s
# cd /var/www
# mkdir sftest && cd sftest
# symfony init-project sftest

Note: Si la page web par défaut du projet n'affiche pas d'images, il se peut que votre vhost ne trouve pas les éléments médias génériques de Symfony ; dans ce cas, un lien symbolique comme ci-dessous devrait régler le problème :

# ln -s /usr/share/php/data/symfony/web/sf web/sf

Note : Vous pourriez tout autant utiliser un alias apache dans votre vhost.

Créons maintenant nos deux applications front et back qui recevront le front-office et la console d'administration de notre projet :

# symfony init-app front 
# symfony init-app back

On crée une base de données dédiée au projet :

# mysql -uroot -p
> CREATE DATABASE sftest CHARACTER SET utf8 COLLATE utf8_general_ci;
> GRANT ALL ON sftest.* TO sftest@localhost IDENTIFIED BY '1234567'
> FLUSH PRIVILEGES;
> \q

Configuration de l'accès à la base de données

D'abord, on renseigne notre DSN MySQL dans le fichier config/databases.yml :

all:
  propel:
    class:          sfPropelDatabase
    param:
      dsn:          mysql://sftest:1234567@localhost/sftest

On fait la même chose pour Propel, dans le fichier config/propel.ini :

propel.database.url = mysql://sftest:1234567@localhost/sftest

Configuration du modèle de données

On crée le schéma de base notre de données, dans le fichier config/schema.yml :

propel:

  blog_authors:
    _attributes:    { phpName: Author }
    id: 
    name:           varchar(255)
    email:          varchar(255)

  blog_posts:
    _attributes:    { phpName: Post }
    id: 
    title:          varchar(255)
    excerpt:        longvarchar
    body:           longvarchar
    author_id:
    created_at:
    updated_at:
  
  blog_comments:
    _attributes:    { phpName: Comment }
    id: 
    post_id:
    author:         varchar(255)
    email:          varchar(255)
    site:           varchar(255)
    content:        longvarchar
    created_at:

  blog_sections:
    _attributes:    { phpName: Section }
    id: 
    name:           varchar(255)

  blog_posts_sections:
    _attributes:    { phpName: PostSection }
    id: 
    post_id:
    section_id:

Il y a beaucoup de magie dans la syntaxe de ce fichier. Retenez juste que les champs id, *_id et *_at sont nommés en vertus de conventions Symfony pour gérer automatiquement clés primaires, clés étrangères et les champs de type DATETIME.

Création d'un jeu de données de test

De même et parce qu'on est des gens sérieux (mais surtout parceque c'est pratique), on crée d'emblée un jeu de données de test (ou fixtures), dans un nouveau fichier data/fixtures/data.yml :

Author:
  NiKo:
    name:    NiKo
    email:   tepafou@fai.com

Post:
  FirstPost:
    title:   Mon premier post !
    excerpt: Un premier billet prometteur...
    body: >
      Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Integer 
      consectetuer congue diam. Sed eu enim. Cras fringilla, erat et pretium 
      tincidunt, elit nibh imperdiet lectus, vel viverra erat velit in  
      metus. Ut ipsum ante, ornare luctus, hendrerit in, ultricies id, est.
    author_id: NiKo
  
  SecondPost:
    title:   Mon deuxième billet
    excerpt: Un deuxième billet tout aussi savoureux.
    body: >
      Suspendisse potenti. Mauris id risus. Cras urna. Etiam vel enim nec 
      dui ultrices condimentum. Curabitur bibendum ultrices quam. Nulla 
      sodales risus eget nunc.
    author_id: NiKo

Section:
  Humeurs:
    name:    Humeurs
  Geek: 
    name:    Geek
  Ubuntu:
    name:    Ubuntu

PostSection:
  # First post categories
  FirstPost_Humeurs:
    post_id: FirstPost
    section_id: Humeurs
  FirstPost_Geek: 
    post_id: FirstPost
    section_id: Geek

  # Second post categories
  SecondPost_Geek:
    post_id: SecondPost
    section_id: Geek
  SecondPost_Geek: 
    post_id: SecondPost
    section_id: Ubuntu

Comment:
  Comment1:
    post_id: FirstPost
    author:  Jean-Paul
    email:   "jp@fai.com"
    site:    "http://blog.jeanpaul.com"
    content: Bravo, belle intervention.

  Comment2:
    post_id: SecondPost
    author:  Jean-Luc
    email:   "jl@fai.com"
    site:    "http://blog.jeanluc.org"
    content: Exactement, vous avez raison.

Ceci fait, on va lancer la génération du fichier SQL et des classes représentant notre modèle, créer les tables physiquement dans notre base et insérer notre jeu de données de test :

# symfony propel-build-all-load back

Vous noterez qu'un seule ligne de commande est à appeller, ce qui simplifie grandement les phases de prototypage.

Note : En cas de modification profonde du modèle de données, il est vivement conseillé de vider le cache symfony :

# symfony cc

Ajout des méthodes __toString() aux objets de données

Afin d'avoir facilement un descripteur texte pour notre objet Author, nous allons implémenter une méthode __toString() dans sa classe associée située dans le fichier lib/model/Author.php :

class Author extends BaseAuthor
{
  public function __toString()
  {
    return $this->getName();
  }
}

Cette méthode retournera le contenu du champs name de l'enregistrement de la table blog_authors correspondant pour identifier l'objet PHP sous la forme d'une chaîne de caractère descriptive. Vous pouvez aussi adapter ce principe pour les objets Post et Section, par exemple.

Génération d'un back-office d'administration des billets

Maintenant, on va générer une interface d'administration de nos objets Post, accessible par un contrôleur /posts depuis notre application back :

# symfony propel-init-admin back posts Post

L'interface d'administration est maintenant accessible via /back_dev.php/posts derrière la racine de l'url de votre instance projet Symfony :-)

Administration des billets

C'est un peu sec par défaut et les sections associées aux billets du blog ne sont pas gérées, il nous faut donc adapter le fichier de configuration du générateur d'admin de Symfony pour ce module, situé dans le fichier apps/back/modules/posts/config/generator.yml :

generator:
  class:               sfPropelAdminGenerator
  param:
    model_class:       Post
    theme:             default

    # Customisation des colones de la vue en liste, lien d'édition sur le titre
    list:
      display:         [=title, excerpt, Author, created_at, updated_at]

    # Customisation du formulaire d'ajout/édition
    edit:
    
      # Champs personnalisés
      fields:
        # Création d'un champs d'administration des sections associées
        post_sections: { type: admin_check_list, params: through_class=PostSection }
    
      # Spécification des champs de formulaire à afficher
      display:         [author_id, title, excerpt, body, post_sections]

Un raffraîchissement des interfaces en mode développement (en appellant le contrôleur back_dev.php dans l'url) affichera nos interfaces modifiées en conséquences. Si vous utilisez le contrôleur de production (/back.php), n'oubliez pas de vider le cache symfony pour visualiser vos modifications :

# symfony cc

On reproduira exactement la même opération pour nos autres objets à administrer (Author, Comment et Section):

# symfony propel-init-admin back authors Author
# symfony propel-init-admin back sections Section
# symfony propel-init-admin back comments Comment

Voila, une vingtaine de minutes nous auront suffit pour générer une application en ligne relativement complète. Il restera à gérer notamment :

Amusez-vous bien :-)

Avril 2007 – Prendre un Café: Gagnez du temps avec Symfony 1.0 et son générateur de back-office

Lors du dernier petit-déjeuner Clever Age que j'ai animé sur les frameworks PHP, j'ai effectué une démonstration des fonctionnalités de génération de back-office existantes dans Symfony : la plupart des gens présents - pour la plupart découvrant la notion même de framework - ont été très impressionnés par la facilité déconcertante avec laquelle il était possible de développer une application complète en très peu de temps et d'étapes techniques grâce au générateur d'admin...

Personnellement, je suis tellement habitué à travailler avec de tels outils désormais que j'oublie parfois comme la vie est plus difficile sans eux... Je vais donc faire une démonstration afin que chacun puisse se faire son idée, sur sa propre machine :)

Pour faire très original, on va créer une petite application sommaire de gestion de weblog, doté des fonctionnalités suivantes :

  • Un auteur par billet
  • Billets multi-catégoriques (on pourrait aussi parler de tags)
  • Commentaires pour chaque billet

L'avantage est que la plupart des frameworks web proposent ce type de tutoriaux, donc ainsi vous pourrez plus aisément comparer :)

Installation de Symfony

Je vous renvoie à la documentation officielle ou à ce tutoriel pour installer Symfony sur votre machine et configurer un vhost apache pour votre nouveau projet. On partira sur la version 1.0.2, soit la dernière version stable disponible à l'heure où sont écrites ces quelques lignes.

Création d'un nouveau projet

Imaginons que votre projet soit créé dans /var/www :

$ sudo -s
# cd /var/www
# mkdir sftest && cd sftest
# symfony init-project sftest

Note: Si la page web par défaut du projet n'affiche pas d'images, il se peut que votre vhost ne trouve pas les éléments médias génériques de Symfony ; dans ce cas, un lien symbolique comme ci-dessous devrait régler le problème :

# ln -s /usr/share/php/data/symfony/web/sf web/sf

Note : Vous pourriez tout autant utiliser un alias apache dans votre vhost.

Créons maintenant nos deux applications front et back qui recevront le front-office et la console d'administration de notre projet :

# symfony init-app front 
# symfony init-app back

On crée une base de données dédiée au projet :

# mysql -uroot -p
> CREATE DATABASE sftest CHARACTER SET utf8 COLLATE utf8_general_ci;
> GRANT ALL ON sftest.* TO sftest@localhost IDENTIFIED BY '1234567'
> FLUSH PRIVILEGES;
> \q

Configuration de l'accès à la base de données

D'abord, on renseigne notre DSN MySQL dans le fichier config/databases.yml :

all:
  propel:
    class:          sfPropelDatabase
    param:
      dsn:          mysql://sftest:1234567@localhost/sftest

On fait la même chose pour Propel, dans le fichier config/propel.ini :

propel.database.url = mysql://sftest:1234567@localhost/sftest

Configuration du modèle de données

On crée le schéma de base notre de données, dans le fichier config/schema.yml :

propel:

  blog_authors:
    _attributes:    { phpName: Author }
    id: 
    name:           varchar(255)
    email:          varchar(255)

  blog_posts:
    _attributes:    { phpName: Post }
    id: 
    title:          varchar(255)
    excerpt:        longvarchar
    body:           longvarchar
    author_id:
    created_at:
    updated_at:
  
  blog_comments:
    _attributes:    { phpName: Comment }
    id: 
    post_id:
    author:         varchar(255)
    email:          varchar(255)
    site:           varchar(255)
    content:        longvarchar
    created_at:

  blog_sections:
    _attributes:    { phpName: Section }
    id: 
    name:           varchar(255)

  blog_posts_sections:
    _attributes:    { phpName: PostSection }
    id: 
    post_id:
    section_id:

Il y a beaucoup de magie dans la syntaxe de ce fichier. Retenez juste que les champs id, *_id et *_at sont nommés en vertus de conventions Symfony pour gérer automatiquement clés primaires, clés étrangères et les champs de type DATETIME.

Création d'un jeu de données de test

De même et parce qu'on est des gens sérieux (mais surtout parceque c'est pratique), on crée d'emblée un jeu de données de test (ou fixtures), dans un nouveau fichier data/fixtures/data.yml :

Author:
  NiKo:
    name:    NiKo
    email:   tepafou@fai.com

Post:
  FirstPost:
    title:   Mon premier post !
    excerpt: Un premier billet prometteur...
    body: >
      Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Integer 
      consectetuer congue diam. Sed eu enim. Cras fringilla, erat et pretium 
      tincidunt, elit nibh imperdiet lectus, vel viverra erat velit in  
      metus. Ut ipsum ante, ornare luctus, hendrerit in, ultricies id, est.
    author_id: NiKo
  
  SecondPost:
    title:   Mon deuxième billet
    excerpt: Un deuxième billet tout aussi savoureux.
    body: >
      Suspendisse potenti. Mauris id risus. Cras urna. Etiam vel enim nec 
      dui ultrices condimentum. Curabitur bibendum ultrices quam. Nulla 
      sodales risus eget nunc.
    author_id: NiKo

Section:
  Humeurs:
    name:    Humeurs
  Geek: 
    name:    Geek
  Ubuntu:
    name:    Ubuntu

PostSection:
  # First post categories
  FirstPost_Humeurs:
    post_id: FirstPost
    section_id: Humeurs
  FirstPost_Geek: 
    post_id: FirstPost
    section_id: Geek

  # Second post categories
  SecondPost_Geek:
    post_id: SecondPost
    section_id: Geek
  SecondPost_Geek: 
    post_id: SecondPost
    section_id: Ubuntu

Comment:
  Comment1:
    post_id: FirstPost
    author:  Jean-Paul
    email:   "jp@fai.com"
    site:    "http://blog.jeanpaul.com"
    content: Bravo, belle intervention.

  Comment2:
    post_id: SecondPost
    author:  Jean-Luc
    email:   "jl@fai.com"
    site:    "http://blog.jeanluc.org"
    content: Exactement, vous avez raison.

Ceci fait, on va lancer la génération du fichier SQL et des classes représentant notre modèle, créer les tables physiquement dans notre base et insérer notre jeu de données de test :

# symfony propel-build-all-load back

Vous noterez qu'un seule ligne de commande est à appeller, ce qui simplifie grandement les phases de prototypage.

Note : En cas de modification profonde du modèle de données, il est vivement conseillé de vider le cache symfony :

# symfony cc

Ajout des méthodes __toString() aux objets de données

Afin d'avoir facilement un descripteur texte pour notre objet Author, nous allons implémenter une méthode __toString() dans sa classe associée située dans le fichier lib/model/Author.php :

class Author extends BaseAuthor
{
  public function __toString()
  {
    return $this->getName();
  }
}

Cette méthode retournera le contenu du champs name de l'enregistrement de la table blog_authors correspondant pour identifier l'objet PHP sous la forme d'une chaîne de caractère descriptive. Vous pouvez aussi adapter ce principe pour les objets Post et Section, par exemple.

Génération d'un back-office d'administration des billets

Maintenant, on va générer une interface d'administration de nos objets Post, accessible par un contrôleur /posts depuis notre application back :

# symfony propel-init-admin back posts Post

L'interface d'administration est maintenant accessible via /back_dev.php/posts derrière la racine de l'url de votre instance projet Symfony :-)

Administration des billets

C'est un peu sec par défaut et les sections associées aux billets du blog ne sont pas gérées, il nous faut donc adapter le fichier de configuration du générateur d'admin de Symfony pour ce module, situé dans le fichier apps/back/modules/posts/config/generator.yml :

generator:
  class:               sfPropelAdminGenerator
  param:
    model_class:       Post
    theme:             default

    # Customisation des colones de la vue en liste, lien d'édition sur le titre
    list:
      display:         [=title, excerpt, Author, created_at, updated_at]

    # Customisation du formulaire d'ajout/édition
    edit:
    
      # Champs personnalisés
      fields:
        # Création d'un champs d'administration des sections associées
        post_sections: { type: admin_check_list, params: through_class=PostSection }
    
      # Spécification des champs de formulaire à afficher
      display:         [author_id, title, excerpt, body, post_sections]

Un raffraîchissement des interfaces en mode développement (en appellant le contrôleur back_dev.php dans l'url) affichera nos interfaces modifiées en conséquences. Si vous utilisez le contrôleur de production (/back.php), n'oubliez pas de vider le cache symfony pour visualiser vos modifications :

# symfony cc

On reproduira exactement la même opération pour nos autres objets à administrer (Author, Comment et Section):

# symfony propel-init-admin back authors Author
# symfony propel-init-admin back sections Section
# symfony propel-init-admin back comments Comment

Voila, une vingtaine de minutes nous auront suffit pour générer une application en ligne relativement complète. Il restera à gérer notamment :

Amusez-vous bien :-)

Avril 2007 – Prendre un Café: Symfony, Admin-Generator et Composants

Dans un précédent billet, nous avons vu comment créer un weblog basique avec l'admin-generator de Symfony. Nous allons reprendre là où nous en étions et ajouter la liste des commentaires à notre back-office de gestion des billets grâce à un simple appel de composant, qui n'est autre qu'un template partiel associé à un contrôleur dédié.

Création du module de gestion des commentaires en back-office

Si ce n'est déjà fait, on crée notre module de gestion des commentaires

# symfony propel-init-admin back comments Comment

Création du composant qui va lister les commentaires d'un billet

Bien. On va maintenant créer un composant postcomments qui affichera la liste des commentaires associés à un objet Post, en créant un nouveau fichier apps/back/modules/posts/actions/components.class.php et en y insérent le contenu ci-dessous :

<?php
class postsComponents extends sfComponents 
{
  
  /**
   * List comments for a given Post
   * 
   */
  public function executePostcomments()
  {
    $post_id = $this->getRequestParameter('id');
    if (!is_null($post_id))
    {
      $c = new Criteria();
      $c->add(CommentPeer::POST_ID, $post_id);
      $c->addDescendingOrderByColumn(CommentPeer::CREATED_AT);
      $this->comments = CommentPeer::doSelect($c);
    }
  }
  
}

On crée maintenant le template partiel associé au contrôleur, dans le fichier apps/back/modules/posts/templates/_postcomments.php :

<?php if (isset($comments)): ?>
  <?php if (count($comments) > 0): ?>
    <?php use_helper('Comment', 'Text') ?>
    <dl>
    <?php foreach ($comments as $comment): ?>
      <dt>
        <?php echo sprintf('Posté le <strong>%s</strong> par <strong>%s</strong> :', 
                           format_date($comment->getCreatedAt(), 'd/MM/yyyy à H:m'),
                           format_comment_author($comment->getAuthor(),
                                                 $comment->getSite())) ?>
      </dt>
      <dd>
        <?php echo simple_format_text($comment->getContent()) ?>
      </dd>
      <dd>
        [<?php echo link_to('Éditer', 'comments/edit?id='.$comment->getId()) ?>]
        [<?php echo link_to('Supprimer', 
                            'comments/delete?id='.$comment->getId(),
                            'confirm=Êtes-vous sûr ?') ?>]
      </dd>
    <?php endforeach; ?>
    </dl>
  <?php else: ?>
    <p>No comment yet.</p>
  <?php endif; ?>
<?php endif; ?>

Utilisation d'un helper pour des tâches courantes de templating

La fonction format_comment_author est un helper maison, que nous définissons dans un nouveau fichier lib/helper/CommentHelper.php :

<?php
/**
 * Returns a formatted html string for author including website link if any
 * 
 * @param  string   $name
 * @param  string   $site
 * @param  boolean  $nofollow
 * @return string 
 */
function format_comment_author($name, $site=null, $nofollow=true)
{
  if (!is_null($site) && preg_match('/^http/i', $site))
  {
    return sprintf('<a href="%s"%s>%s</a>', 
                   $site, 
                   $nofollow === true ? ' rel="nofollow"' : '',
                   $name);
  }
  else
  {
    return $name;
  }
}

Mise à jour du back-office de gestion des billets

Ceci fait, modifions le fichier de configuration du back-office d'administration des billets créé précemment et situé dans le fichier apps/back/modules/posts/config/generator.yml, afin d'appeller notre nouveau composant postcomments pour la vue d'édition d'un billet :

  [...]

    # Customisation du formulaire d'ajout/édition
    edit:
      
      [...]

      # Affichage d'une sélection de champs
      display:         [author_id, title, excerpt, body, post_sections, ~postcomments]

Vous noterez le caractère ~ précedant le nom du composant : encore une convention Symfony qui nous simplifie la vie :)

Gestion de l'échappement

Vous avez tous déjà entendu parler des failles XSS ? Pour nous en prémunir partiellement, nous allons activer l'échappement automatique des contenus passés à une vue, en ajoutant ces directives dans le fichier apps/back/config/settings.yml :

all:
  .settings:
    escaping_strategy: both
    escaping_method:   ESC_ENTITIES

Ainsi, dans notre cas toutes les chaînes seront échappées en entités HTML pour plus de sécurité. Pour plus d'information, rendez-vous dans la section dédiée de la documentation officielle.

Au final, voici ce que ça donne quand on édite un billet :

Affichage des commentaires d'un billet

Champs virtuels

Notre liste de billets, pour l'instant, ne nous informe pas pour chacun le nombre de commentaires associés. On va y remédier simplement en créant un getter ad-hoc dans notre objet de donnée Post et en appellant le champs virtuel associé. Dans le fichier lib/model/Post.php, on rajoute la méthode suivante :

public function getCommentsNumber()
  {
    return $this->countComments();
  }

Et dans le fichier apps/back/modules/posts/config/generator.yml, on affiche le champs virtuel comments_number dans la vue en liste :

  [...]

    # Customisation des colones de la vue en liste
    list:
      display:         [=title, excerpt, Author, comments_number, created_at, updated_at]

Voici ce que ça donne :

Liste des billets, avec nombre de commentaires associés

En conclusion

Voila, notre application prend forme doucement. On pourrait passez des heures à ajouter des détails par-ci par-là, mais je vous laisse le faire en compagnie de la documentation :)

Avril 2007 – Prendre un Café: Symfony, Admin-Generator et Composants

Dans un précédent billet, nous avons vu comment créer un weblog basique avec l'admin-generator de Symfony. Nous allons reprendre là où nous en étions et ajouter la liste des commentaires à notre back-office de gestion des billets grâce à un simple appel de composant, qui n'est autre qu'un template partiel associé à un contrôleur dédié.

Création du module de gestion des commentaires en back-office

Si ce n'est déjà fait, on crée notre module de gestion des commentaires

# symfony propel-init-admin back comments Comment

Création du composant qui va lister les commentaires d'un billet

Bien. On va maintenant créer un composant postcomments qui affichera la liste des commentaires associés à un objet Post, en créant un nouveau fichier apps/back/modules/posts/actions/components.class.php et en y insérent le contenu ci-dessous :

<?php
class postsComponents extends sfComponents 
{
  
  /**
   * List comments for a given Post
   * 
   */
  public function executePostcomments()
  {
    $post_id = $this->getRequestParameter('id');
    if (!is_null($post_id))
    {
      $c = new Criteria();
      $c->add(CommentPeer::POST_ID, $post_id);
      $c->addDescendingOrderByColumn(CommentPeer::CREATED_AT);
      $this->comments = CommentPeer::doSelect($c);
    }
  }
  
}

On crée maintenant le template partiel associé au contrôleur, dans le fichier apps/back/modules/posts/templates/_postcomments.php :

<?php if (isset($comments)): ?>
  <?php if (count($comments) > 0): ?>
    <?php use_helper('Comment', 'Text') ?>
    <dl>
    <?php foreach ($comments as $comment): ?>
      <dt>
        <?php echo sprintf('Posté le <strong>%s</strong> par <strong>%s</strong> :', 
                           format_date($comment->getCreatedAt(), 'd/MM/yyyy à H:m'),
                           format_comment_author($comment->getAuthor(),
                                                 $comment->getSite())) ?>
      </dt>
      <dd>
        <?php echo simple_format_text($comment->getContent()) ?>
      </dd>
      <dd>
        [<?php echo link_to('Éditer', 'comments/edit?id='.$comment->getId()) ?>]
        [<?php echo link_to('Supprimer', 
                            'comments/delete?id='.$comment->getId(),
                            'confirm=Êtes-vous sûr ?') ?>]
      </dd>
    <?php endforeach; ?>
    </dl>
  <?php else: ?>
    <p>No comment yet.</p>
  <?php endif; ?>
<?php endif; ?>

Utilisation d'un helper pour des tâches courantes de templating

La fonction format_comment_author est un helper maison, que nous définissons dans un nouveau fichier lib/helper/CommentHelper.php :

<?php
/**
 * Returns a formatted html string for author including website link if any
 * 
 * @param  string   $name
 * @param  string   $site
 * @param  boolean  $nofollow
 * @return string 
 */
function format_comment_author($name, $site=null, $nofollow=true)
{
  if (!is_null($site) && preg_match('/^http/i', $site))
  {
    return sprintf('<a href="%s"%s>%s</a>', 
                   $site, 
                   $nofollow === true ? ' rel="nofollow"' : '',
                   $name);
  }
  else
  {
    return $name;
  }
}

Mise à jour du back-office de gestion des billets

Ceci fait, modifions le fichier de configuration du back-office d'administration des billets créé précemment et situé dans le fichier apps/back/modules/posts/config/generator.yml, afin d'appeller notre nouveau composant postcomments pour la vue d'édition d'un billet :

  [...]

    # Customisation du formulaire d'ajout/édition
    edit:
      
      [...]

      # Affichage d'une sélection de champs
      display:         [author_id, title, excerpt, body, post_sections, ~postcomments]

Vous noterez le caractère ~ précedant le nom du composant : encore une convention Symfony qui nous simplifie la vie :)

Gestion de l'échappement

Vous avez tous déjà entendu parler des failles XSS ? Pour nous en prémunir partiellement, nous allons activer l'échappement automatique des contenus passés à une vue, en ajoutant ces directives dans le fichier apps/back/config/settings.yml :

all:
  .settings:
    escaping_strategy: both
    escaping_method:   ESC_ENTITIES

Ainsi, dans notre cas toutes les chaînes seront échappées en entités HTML pour plus de sécurité. Pour plus d'information, rendez-vous dans la section dédiée de la documentation officielle.

Au final, voici ce que ça donne quand on édite un billet :

Affichage des commentaires d'un billet

Champs virtuels

Notre liste de billets, pour l'instant, ne nous informe pas pour chacun le nombre de commentaires associés. On va y remédier simplement en créant un getter ad-hoc dans notre objet de donnée Post et en appellant le champs virtuel associé. Dans le fichier lib/model/Post.php, on rajoute la méthode suivante :

public function getCommentsNumber()
  {
    return $this->countComments();
  }

Et dans le fichier apps/back/modules/posts/config/generator.yml, on affiche le champs virtuel comments_number dans la vue en liste :

  [...]

    # Customisation des colones de la vue en liste
    list:
      display:         [=title, excerpt, Author, comments_number, created_at, updated_at]

Voici ce que ça donne :

Liste des billets, avec nombre de commentaires associés

En conclusion

Voila, notre application prend forme doucement. On pourrait passez des heures à ajouter des détails par-ci par-là, mais je vous laisse le faire en compagnie de la documentation :)