Bla bla blog

Aller au contenu | Aller au menu | Aller à la recherche

jeudi 16 avril 2009

Zend_Db : Utilisation du mapping

Après avoir vu comment définir le mapping dans ce précédent article, nous allons voir comment utiliser les classes de ce mapping pour faire du CRUD (Create, Read, Update, Delete) sur nos tables.

Gestion des connexions

Attention Zend_Db_Table utilise l'interface PDO (présente de la version 5.1 de PHP) pour se connecter votre base de données, pensez donc à activer les extensions correspondantes dans le fichier php.in (ie php_pdo.dll et php_pdo_mysql.dll pour une base de données MySql).

Ensuite dans le code il suffit de paramétrer l'adaptateur qui permettra d'établir les connexion de la manière suivante :

    $params = array(
        'host'     => '127.0.0.1',
        'username' => 'root',
        'password' => 'MY_PASSWORD',
        'dbname'   => 'test'
    );
    
    $db = Zend_Db::factory('Pdo_Mysql', $params);
    Zend_Db_Table::setDefaultAdapter($db);

On voit que la méthode static setDefaultAdapter() permet d'enregistrer l'adapteur auprès de la classe Zend_Db_Table, ainsi les connexions/déconnexions seront établies à la demande par cette dernière.

Créations

Pour effectuer une insertion en base de données, il suffit d'instancier la classe mappée sur la table correspondante (la classe Topic pour la table Topics dans notre exemple), puis appeler la méthode createRow() héritée de la classe Zend_Db_Table

$topic = new Topic();
$topic = $topic->createRow();

Vient ensuite l'affectation des différents champs de la table. Ces affectations peuvent s'effectuer en simulant des appels aux attributs de l'objet $topic :

$topic->name=$name;
$topic->forum_id=$id;
$topic->save();

ou en passant un tableau de paramètre à la méthode createRow

$data=array("title"=>$title,"topic_id"=>$id);
$post = $post->createRow($data);
$post->save();

Sans oublier la sauvegarde pour que les modifications soient commitées.

Sélections

Pour les sélections le mécanisme est exactement le même, c'est à dire que l'on commence par instancier la classe correspondant au nom de la table que l'on veut interroger avant d'utiliser les méthodes suivantes :

  • find() pour faire une recherche en filtrant sur la clé primaire
  • fetchAll() pour récupérer plusieurs résultats (RowSet) en ayant la possibilité de filtrer via les paramètres de la méthode
  • fecth() identique au fetchAll() sauf qu'un seul enregistrement (Row) sera retourné
$forum = new Forum();
$all = $forum->fetchAll(); //FetchAll retourne un RowSet donc parcours
foreach($all as $item){
     echo "id:{$item->id}, name:{$item->name}";
}

On voit dans cet exemple qu'en présence d'un RowSet, il faudra le parcourir de manière à récupérer les enregistrement un à un, ce sont en fait des objets Row qui permettent la lecture des valeurs de l'enregistrement.

Pour aller plus loin, comme nous avons défini des relations entre nos table Forum <1_n> Topic <1_n> Post, il est possible d'utiliser ces relations lors d'une selection via les méthode findDependentRowSet("Topic") ou findTopic() pour récupérer tous les enregistrements référençant un Forum. Cette technique est très appréciable pour naviguer dans la structure d'une base de données relationnelle sans ce soucier du SQL et des jointures.

$forum = new Forum();
$forums = $forum->find($pk);
$forum = $forums->current();//on récupère un seul enregistrement forum
echo "FORUM id:{$forum->id}, name:{$forum->name}\n";
$topics = $forum->findDependentRowset("Topic"); //recherche de tous les topics relatifs
foreach($topics as $topic){
    echo "\t TOPIC id:{$topic->id}, name:{$topic->name}\n";
    $posts = $topic->findPost(); //recherche de tous les posts relatifs
    foreach($posts as $post){
                echo "\t\t POST id:{$post->id}, title:{$post->title}\n";
    }
}

Tous les sources de cette démo sont en pièce jointe, il vous faudra simplement créer une base de données "test" ainsi que les trois tables Forums, Topics et Posts. Bon courage et merci pour vos éventuels retours.

Zend_Db : Définition d'un mapping objet relationnel

Dans ZF (Zend Framework) le mapping objet relationnel a été défini via les design patterns "table data gateway" et "row data gateway" inventés par Martin Fowler. Ces patterns permettent d'accéder ou de manipuler le contenu de table via des objets, ici ces objets seront de simples wrapper de notre structure relationnelle, donc chaque table est associée à une classe qui sera définie par le développeur en respectant un certain nombre de règles (héritage, redéfinition, etc) que nous verrons ici.

Un exemple de modèle relationnel

Pour illustrer les possibilités offertes par ce framework, nous prendrons un exemple simple : le forum de discussion, dont le modèle relationnel simplifié serait le suivant :
Forum modele relationnel
Donc simplement trois tables, avec une clé primaire id auto incrémentée sur chaque table et des clés étrangères de posts vers topics et de topics vers forums.

Définition du mapping

En respectant les principes des patterns précités, nous obtenons donc trois classes qui héritent de la classe Zend_Db_Table (fournie par ZF)
Mapping forum definition

Personnalisation du mapping

Toutefois ce mapping ne fonctionnera qu'à condition que votre table porte exactement le même nom que votre classe et que la clé primaire soit le champ ID et qu'elle soit auto-incrémentée. Pour tout autre cas de figure il faudra redéfinir les attributs $_name, $_id et $_sequence dans votre classe. Ainsi pour la classe Topic, nous aurons le code suivant :

<?php
require_once("Zend/Db/Table.php");

class Topic extends Zend_Db_Table{
    
    protected $_primary="id"; //clé primaire 
    protected $_sequence=true; //true est la valeur par défaut, pour une clé primaire auto-incrémentée
                                              //false entraîne l'obligation pour le développeur de renseigner la valeur de sa clé
                                              //une chaîne de caractère, pour les PK de type séquence (uniquement sur certains type de SGBDR)
    protected $_name="topics"; //nom de la table correspondant à cette classe

}
?>

Définition des relations

Dans ZF, la définition des relations doit être faite dans chaque classe. Elle s'appuie sur les relations définies au niveau de la base de données, c'est à dire les clés étrangères. Cette définition est importante car elle permet de "naviguer" dans la grappe d'objets récupérée, par exemple récupérer tous les posts relatifs à un topic, ou à partir d'un post retrouver son topic.

Prenons l'exemple de la table TOPICS, chaque enregistrement dans cette table doit référencer via une clé étrangère une entrée dans la table FORUMS, tout comme les enregistrements dans la table POSTS doivent référencer les entrées dans la table TOPICS. Voyons comment matérialiser ces relations au niveau de la classe Topic :

<?php
require_once("Zend/Db/Table.php");

class Topic extends Zend_Db_Table{
   [...]  

   //$_refernceMap est un tableau associatif qui représente toutes les clés étrangères ou relations de la 
   //table TOPICS avec d'autre tables
   protected $_referenceMap=array("forumKey"=>array(                 //forumKey est l'identifiant de cette relation, utile pour requêter la structure objet lorsqu'il y a plusieurs relations
                                                     "columns"=>array("forum_id"),  //Nom de la colonne portant la clé étrangère
                                                     "refTableClass"=>"Forum",       //Nom de la table référencée
                                                     "refColumns"=>array("id")));     //Nom de la colonne référencée (PK)

  //Noms de toutes les tables qui ont des relations avec la table TOPICS  
  protected $_dependentTables=array("Post");

}
?>

Nous venons de voir comment définir un mapping objet relationnel avec le module Zend_Db de ZF. Pour aller plus loin je vous propose la documentation de ZF.

mardi 17 février 2009

JQuery à la sauce Zend

Dans sa version 1.7, ZF (Zend Framework) a vu pas mal de nouveautés, parmi lesquels il faut d'après moi relever les extensions :

  • Zend_AMF pour un support du protocole AMF d'Adobe. On peut ainsi imaginer un frontal Flex/AS/Flash avec un back-end PHP, c'était déjà le cas avant via HTTP ou les web services, l'intérêt du protocole AMF étant de permettre au serveur de mettre à jour les clients sans qu'ils ne l'aient sollicité.
  • ZendX_JQuery pour un support du célèbre framework AJAX qui est en train de supplanter tous ces concurrents. Pour vous faire une idée des widgets mis à votre disposition, et la manière d'utiliser cette extension je vous conseille cette démo

Pour le reste des nouveautés il s'agit surtout de mise à jour des librairies existantes, d'amélioration des perf pour le Zend_Loader et de la corrections de quelque 300 bugs.

Voici un post qui donne un peu plus de détail :

Zend Framework 1.7.0 is now available from the Zend Framework download site: http://framework.zend.com/download/latest

This release introduces many new components and features, including:

* Zend_Amf with support for AMF0 and AMF3 protocols * Dojo Toolkit 1.2.1 * Support for dijit editor available in the Dojo Toolkit * Zend_Service_Twitter * ZendX_JQuery in extras library * Metadata API in Zend_Cache * Google book search API in Zend_Gdata * Preliminary support for GData Protocol v2 in Zend_Gdata * Support for skip data processing in Zend_Search_Lucene * Support for Open Office XML documents in Zend_Search_Lucene indexer * Performance enhancements in Zend_Loader, Zend_Controller, and server components * Zend_Mail_Storage_Writable_Maildir enhancements for mail delivery * Zend_Tool in incubator * Zend_Text_Table for formatting table using characters * Zend_ProgressBar * Zend_Config_Writer * ZendX_Console_Unix_Process in the extras library * Zend_Db_Table_Select support for Zend_Paginator * Global parameters for routes * Using Chain-Routes for Hostname-Routes via Zend_Config * I18N improvements - Application wide locale for all classes - Data retrieving methods are now static - Additional cache handling methods in all I18N classes - Zend_Translate API simplified * File transfer enhancements - Support for file elements in subforms - Support for multifile elements - Support for MAX_FILES_SIZE in form - Support for breaking validation chain - Support for translation of failure ,messages - New IsCompressed, IsImage, ExcludeMimeType, ExcludeExtension validators - Support for FileInfo extension in MimeType validator * Zend_Db_Table_Select adapater for Zend_Paginator * Support for custom adapters in Zend_Paginator * More flexible handling of complex types in Zend_Soap

In addition, almost three hundred bugs have been fixed:

http://framework.zend.com/issues/sec...equestId=10903

The Zend Framework team would like to thank everyone who made this release possible. As always, our generous ZF community has provided countless new features, bug fixes, documentation translations, etc. We'd also like to thank Adobe Systems and Wade Arnold for contributing the new Zend_Amf component. A big thanks to PHP Belgium and everyone who participated in bug hunt day (http://www.bughuntday.org/) and/or the Zend Framework bug hunt week. Finally, we'd like to thank all of those whom we've forgotten to thank above. Once again, we're reminded that Zend Framework is about much more than code, it is about community. See y'all online.

,Wil

mercredi 17 septembre 2008

Configuration de PHPEdit

Ce billet s'adresse à tout ceux qui cherchent une alternative Open Source à l'environnement Zend Studio. L'environnement qui a retenu mon attention est PHPEclipse. Comme Zend Studio il repose sur Eclipse, il s'agit d'un plugin à installer.

Installer l'environnement AMP

Avant de configurer PHPEclipse il faut avoir installer l'environnement AMP (Apache, Mysql, PHP) sur votre poste. Deux possibilités s'offrent à vous :

  1. Installer une distribution pré-packagée de AMP comme XAMPP
  2. Configurer les différents éléments par vos propres moyens (présenté dans ce billet)

Installer le plugin PHPEclipse

Après avoir installer l'environnement Eclipse (disponible sous licence EPL) vous avez le choix entre les deux modes d'installation :

  • via le mode d'installation à distance
  • après avoir téléchargé le plugin

Ces deux modes d'installation sont présentés sur le site de PHPEclipse dans la rubrique installation, ou dans ce billet

Configurer le plugin PHP Eclipse

Tout se passe dans le menu window>Preferences d'Eclipse

Interfacer Eclipse et AMP

Pour les utilisateurs de XAMPP comme pour ceux qui ont installé les différents modules séparément, il suffit d'indiquer les emplacements des répertoires d'installation des différentes composantes dans PHPEclipse>PHP External Tools Attention pour pouvoir démarrer Apache j'ai dû modifier l'option de démarrage en remplaçant -c "DocumentRoot {0}" par -k start. De ce fait l'option "Document Root" ne sera plus prise en compte, mais notre serveur démarrera... Il est maintenant possible de gérer le démarrage et l'arrêt de ces composants via ala barre d'outil d'Eclipse phpEditToolBox

Configuration des projets

Dans le menu PHPEclipse>Project Defaults, il vous suffit de renseigner :

  • L'URL a renseigner pour tester votre projet. Si vous travaillez avec Zend Framework indiquez http://localhost/ à condition que le DocumentRoot d'apache pointe sur le répertoire de votre projet. Sinon il vous faut définir un Alias (à condition de ne pas travailler avec Zend Framework) ou un virtual host au niveau de la configuration d'Apache. Pour plus d'information, consultez cet article
  • Laissez le "Document Root" inchangé puisqu'il n'est pas pris en compte
  • Dans la partie Include Path, vous pouvez renseigner tous les emplacements où on été placées vos librairies (Zend, PEAR, etc.)

Zend Framework en version 1.6

Depuis le 2 septembre la version 1.6 de Zend Framework est sortie. Rien de véritablement nouveau si ce n'est l'intégration et le support de DOJO, la célèbre librairie AJAX. Cette intégration vous permet de mettre en place très facilement des champs HTML avec auto-completion par exemple. A noter tout de même que les performances se sont nettement dégradées dans cette verison (environ 10%). La version 1.7 ne devrait donc pas tarder pour corriger le tir, en attendant la version 2.0 et le "scaffolding" (bien connu des développeurs 'on rails')