Bonjour,
Voilà j’écris cet article pour partager une solution sur un formulaire symfony qui contient un widget start_date et end_date utilisant sfWidgetFormI18nDate.
Le problème était de pouvoir, en fonction de la start_date, définir une end_date minimale dans un validateur.
La solution était pour ce formulaire de surcharger la méthode doBind pour récupérer les valeurs du start_date et définir le minimum pour le end_date.
Voici le code pour la solution :
|
Voilà j’espère que cette solution pourra aider du monde
Merci à Lermit et Yochima pour leur aide.
Vous l’aurez compris ces temps ci je fait du symfony ! Et aujourd’hui je vais tenter de présenter comment intégrer un annuaire LDAP au plugin sfDoctrineGuard.
Je passe sous silence l’installation qui est bien documenté dans la doc pour en venir directement au point manquant.
Vous trouverez la doc ici : http://www.symfony-project.org/plugins/sfDoctrineGuardPlugin
La documentation propose d’utiliser une option dans notre fichier app.yml : check_password_callable. Ceci est exacte (bien heureusement) mais incomplet.
En effet la validation d’un utilisateur par sfGuard se fait en plusieurs étapes et ce paramètre ne permet que de valider l’exactitude du mot de passe. Il faut donc que les utilisateurs soit présent dans la base de données de sfGuard. Ceci ne nous convenant pas nous allons contourner le problème.
Les options dans app.yml
En plus de l’option check_password_callable nous allons devoir utiliser l’option retrieve_by_username_callable. Cette dernière option va nous permettre de spécifier quelle fonction statique nous utiliserons pour récupérer l’objet représentant notre utilisateur. Ce qui nous donne donc pour notre fichier app.yml :
app:
sf_guard_plugin:
check_password_callable: [UserMap, checkPassword]
retrieve_by_username_callable: [UserMap, getByUsername]
Ici nous spécifions donc que pour contrôler la validité du mot de passe nous utilisons UserMap::checkPassword($username,$password) et pour récupérer l’objet utilisateur UserMap::getByUsername($username).
Voyons comment construire ces classes
Notre objet UserMap
Notre objet UserMap doit posséder deux fonctions statiques que nous avons spécifié dans notre configuration :
- public static function checkPassword($username, $passsword);
- public static function getByUsername($username);
Ce qui nous donne une classe construite comme ceci (à adapter) :
class UserMap
{public static function getByUsername($username)
{
$user = Ldap::getByUsername($username);
return $user;
return null;
}
public static function checkPassword($username, $password)
{
return $this->getByUsername($username)->checkPassword($password);
}
}
Ces fonctions agissent sur l’objet LdapUser que nous allons détailler.
Notre objet utilisateur
Pour pouvoir être utilisé par sfGuard notre objet LdapUser doit étendre la classe PluginsfGuardUser et redéfinir quelques fonctions :
- checkPassword : que nous utilisont dans la classe UserMap pour vérifier le mot de passe d’un utilisateur
- getIsActive : que sfGuard utilise pour vérifier que l’utilisateur est valide.
Ceci nous donne donc
class PockostUser extends PluginsfGuardUser
{
public function checkPassword($password)
{
if(… verifier le mot de passe …)
return true;
else
return false;
}
public function getIsActive()
{
return … validité de l’utilisateur …;
}
}
Vous pouvez maintenant utiliser votre authentification sans problème !
Conclusion
Même si documentation de sfDoctrineGuard n’est pas des plus importante en cherchant un peu dans le code on trouve beaucoup de fonctionnalités intéressantes comme celle présenté ici pour surcharger la fonction de récupération d’utilisateur.
SlapORM
Depuis quelque temps je recherche une méthode simple d’accéder à mes entrées LDAP via symfony. Il existe bien plusieurs solutions pour authentifier nos utilisateurs depuis l’annuaire mais quand on parle de modification ceci est une toute autre histoire ! Nous allons donc voir ici comment manipuler nos entrées LDAP à l’aide du plugin slapOrm. Il va s’en dire que quelques bases de php/symfony ainsi que de l’architecture LDAP sont nécessaires à la compréhension de cet article.
slapOrm késako ?
Commençons par replacer les choses dans leurs contextes. Un annuaire LDAP est, comme son nom l’indique, un annuaire. Il stocke donc des données sous forme hiérarchique et ceci de manière optimisée pour la lecture. Le meilleur exemple pour vous schématiser ce concept est de vous imaginer l’annuaire téléphonique. Dans celui ci les numéro de téléphone sont stocké sous forme hiérarchique (L’annuaire, contient des noms de villes qui contiennent des personnes qui possèdent un à plusieurs numéros de téléphone.) aussi il est assez simple de retrouver un numéro de téléphone à l’aide de cette hiérarchie. Le revers de la médaille est la difficulté rencontrée pour écrire dans celui ci. Un simple rapport du temps que vous mettez à trouver un numéro de téléphone par rapport au temps que vous mettez pour apparaître dans l’annuaire vous montre clairement la limite ! Nous utiliserons dans cet article OpenLDAP comme serveur LDAP.
Un ORM pour object-relational mapping ou mapping objet-relationnel en français est une technique de programmation permettant d’accéder à des données d’une base de données relationnelle sous forme d’objet. Ici dire que nous utilisons un ORM pour accéder à notre annuaire est un abus de langage.
Ce que nous allons faire réellement est de créer un abstraction de la hiérarchie de l’annuaire pour pouvoir l’utiliser avec des objets simples. En gros nous allons spécifier que nos utilisateurs ce trouve dans tel branche de l’annuaire et nous allons avoir un objet pour pouvoir y accéder simplement.
Vous l’aurez compris c’est le plugin slapOrm qui nous permet de faire ceci. Aux vus du manque flagrant de documentations sur le projet je vais tenter d’exprimer aux mieux les différents points d’utilisation ici.
Installation
slapOrm ne bénéficit pas encore d’une validation dans les dépôts officiels des plugin de symfony aussi nous allons donc opter pour une installation manuel ! Le plus simple est de télécharger et d’extraire les sources du plugin dans le dossier « plugins » de symfony.
$ wget http://download.github.com/chanmix51-slapOrm-472ba3c.tar.gz
$ tar xvf chanmix51-slapOrm-472ba3c.tar.gz -C /path/vers/dossier/plugins/
$ mv /path/vers/dossier/plugins/chanmix51-slapOrm-472ba3c /path/vers/dossier/plugins/slapOrmPlugin
Ceci est bien entendu à adapter à la dernière version du plugin.
Une fois ceci effectué nous allons activer le plugin dans la configuration de symfony. Editer donc le fichier config/ProjectConfiguration.class.php et activer le plugin
$ vi config/ProjectConfiguration.class.php
…
public function setup()
{
…
$this->enablePlugins(‘slapOrmPlugin’);
….
}
…
Vous avez maintenant installé le plugin. Vous remarquerez que deux nouvelles actions sont disponible avec la commande symfony.
slaporm
:build-form Generate forms associated to the LDAP model classes
:build-model Generate LDAP model classes based on the schema definition
Sans plus attendre continuons la configuration pour nous connecter au serveur LDAP.
Connexion au serveur
La connexion au serveur LDAP se fait avec le fichier de configuration de l’application (les variables de configuration app_ldap_host, app_ldap_port, app_ldap_dn et app_ldap_pass). Nous allons donc éditer notre fichier de configuration app.yml de notre application (ici frontend) et remplir le fichier avec les options correspondantes à nos besoins.
$ vi apps/frontend/config/app.yml
all:
ldap:
host: 127.0.0.1
port: 389
dn: cn=admin,ou=users,dc=exemple,dc=com
pass: password
Création du schéma
Nous allons maintenant configurer le schéma de notre ORM. C’est ici que nous allons spécifier les emplacements de nos entrées dans l’annuaire ainsi que les classes et attributs qui lui sont liés. Ils nous faut donc savoir plusieurs choses :
- Le nom que nous voulons donner à l’objet (le nom de la classe qui sera généré)
- L’emplacement dans la hiérarchie des entités et leur nomination (le dn et rdn, ex : ou=users,dc=exemple,dc=com pour le dn et cn pour le rdn)
- Les « objectClass » utilisé par l’objet (ex: inetOrgPerson, posixAccount)
- les attributs utilisés (ex: sn, cn, mail, …)
Il nous faut ensuite construire un fichier schema.yml dans le dossier config/slaporm construit de la sorte
ObjectName:
dn: « ou=here,dc=exemple,dc=com »
objectClass: [objectClass1, objectClass2]
rdn: myRdn
attributes:
attributes1: { type: attributeType, param1: value, param2: value }
attributes2: { type: attributeType, param1: value, param2: value }
attributes3: { type: attributeType, param1: value, param2: value }
Le paramètre type peut contenir une valeurs parmis les suivantes : dn, integer, mail ou string ceci modifiant le conportemant du plugin en ce qui concerne la génération automatique de formulaire.
Voici un exemple de fichier de configuration schema.yml
User:
dn: « ou=users,dc=exemple,dc=com »
objectClass: [posixAccount, inetOrgPerson]
rdn: cn
attributes:
cn: { type: string, length: 32768, multiple: false, required: true }
gidNumber: { type: string, length: 32768, multiple: false, required: true }
givenName: { type: string, length: 32768, multiple: false }
homeDirectory: { type: string, length: 32768, multiple: false, required: true }
mail: { type: mail, multiple: false }
sn: { type: string, length: 32768, multiple: false }
uid: { type: string, length: 32768, multiple: true, required: true }
uidNumber: { type: string, length; 32769, multiple: false, required: true }
userPassword: { type: string, length: 32768, multiple: false }Group:
dn: « ou=groups,dc=exemple,dc=com »
objectClass: [posixGroup]
rdn: cn
attributes:
cn: { type: string, length: 32768, multiple: false, required: true }
gidnumber: { type: string, length: 32768, multiple: false, required: true }
userpassword: { type: string, length: 32768, multiple: false }
memberuid: { type: string, length: 32768, multiple: true }
description: { type: string, length: 32768, multiple: false }
Attention à bien respecter les espaces (toujours par groupe de deux).
Créer une entrée
La création d’une entrée est donc intimement lié à la création d’un objet ! Ici nous allons créer une entrée de type « User » définit plus haut. Pour cela nous instantion la classe User et utilisons les fonctions magique de type set et get pour spécifier les attributs de l’objet. Attention tout de même tout les fonctions set et get pour fonctionner doivent n’avoir qu’une majuscule : La première lettre du nom de l’attribut sa suite étant en minuscule. Si vous spécifier une autre majuscule elle sera automatiquement mis en minuscule et précédé par un « underscore » (_).
La sauvegarde de l’objet dans l’annuaire est quand à elle réalisé par la « classe map » de la classe entité expliqué ci dessus. Ainsi nous pouvons sur n’importe qu’elle classe entité utiliser la fonction getMapInstance().
Puisqu’il n’y a rien de plus compréhensible qu’un peu de code
$user = new User();
$user->setCn(« toto4″);
$user->setGidnumber(« 10001″);
$user->setHomedirectory(« /home/toto4″);
$user->setUid(array(« toto »));
$user->setUidnumber(« 1004″);
$user->setUserpassword(« toto »);
$user->setSn(array(‘toto4′));
$user->setMail(array(‘romain42@gmail.com’));
$user->getMapInstance()->save($user);
Attention tout de même si vous avez des attributs de type boolean (1.3.6.1.4.1.1466.115.121.1.7) vous devez spécifier TRUE ou FALSE (en majuscule).
Récupérer un ou plusieurs objets
Le plus simple pour récupérer des informations est de récupérer toutes les entités pour une classe entité données (Exemple: récupérer tout les utilisateurs). Pour ceci dans la classe Map il suffit d’exécuter la fonction findAll(). Exemple
$users = SlapOrm::getMapInstanceOf(‘User’)->findAll();
?>
There are <?php echo count($users) ?> users in this result:
<ul>
<?php foreach($users as $user): ?>
<li><?php echo $user->getCn() ?> has mail : <?php echo $user->getMail() ?></li>
<?php endforeach ?>
</ul>
Il existe aussi la fonction getByRdn qui vous permet de rechercher une entités à l’aide de son RDN. Exemple
$user = SlapOrm::getMapInstanceOf(‘User’)->getByRdn(« lermit »);
Enfin pour rechercher au plus fin il existe aussi les fonctions addAndFilter et addOrFilter qui sont détaillées dans la documentation officielle.
Références
* GitHud de slapOrm : https://github.com/chanmix51/slapOrm/wiki
* Site du langage YAML : http://www.yaml.org/
Les addons de vim
Vim à la possibilité d’étendre ses possibilités au moyen de petit (ou pas) script. Nous allons en voir quelques uns ici qui nous serons utile.
Navigation entre action et template
Nous allons commencer notre balade avec un script qui va nous permettre au moyen de la touche <F8> de passer d’un fichier action à un fichier template et inversement.
Cet addon s’appelle symfony.vim et est disponible ici dans se version 0.7. L’installation de ce script sera assez simple. Nous allons récupérer le script, le placer dans le dossier ~/.vim/plugin/ et l’activer dans notre fichier vimrc. En route !
$ wget http://www.vim.org/scripts/download_script.php?src_id=8739
…
100%[======================================>] 7 876 –.-K/s ds 0,1s2010-09-01 23:37:43 (61,9 KB/s) – «download_script.php?src_id=8739» sauvegardé [7876/7876]
$ mv download_script.php\?src_id\=8739 symfony.vim
$ mv symfony.vim ~/.vim/plugin/
Ajoutons à notre fichier vimrc ces quelques lignes
silent map <F8> :SfSwitchView <CR>
Ceci nous permet de lier la touche [F8] à l’action de changement de fichier entre action et template.
Fermer les balises HTML
Nous allons utiliser un deuxième script qui va nous permettre de fermer les balises HTML avec le raccourcie clavier [CTRL] + [_]. Le plugin se trouve ici dans sa version 0.9.1
L’installation est semblable
$ wget http://www.vim.org/scripts/download_script.php?src_id=4318
…2010-09-01 23:46:40 (30,2 KB/s) – «download_script.php?src_id=4318» sauvegardé [12853]
$ mv download_script.php\?src_id\=4318 closetag.vim
$ mv closetag.vim ~/.vim/plugin/
Cette fois nous n’allons plus lier le script à une combinaison de touche mais à un type de fichier. Ici HTML, XML, XSL et PHP
au Filetype html,xml,xsl,php source ~/.vim/plugin/closetag.vim
Naviguer dans notre projet
Un des plugins les plus utiles pour transformer réellement vim en IDE est le plugin « Project » qui va nous permettre de voir l’arborescence de notre projet et de naviguer entre les dossiers de celui ci.
Le fonctionnement de Project est assez simple mais aussi très astucieux. En effet le plugin génère un fichier .vimproject à la racine de votre répertoire personnel qui servira de base à toute la hiérarchie, c’est à dire qu’il contiendra les noms des fichiers, leurs chemins, leurs dossiers parents, etc … Ce fichier n’étant pas super lisible tel quel, Project nous l’affiche de manière plus « userfrendly » à l’aide de la commande :Project. Passons tout de suite à l’installation, nous reviendrons sur l’utilisation plus tard.
Comme pour les autres plugin l’installation est très simple. Nous récupérons la dernière version à cette adresse, décompressons l’archive dans ~/.vim (il y a deux dossiers : plugin – le plugin – et doc – qui est la documentation du plugin et que nous allons laisser dans le dossier ~/.vim/doc/).
$ wget http://www.vim.org/scripts/download_script.php?src_id=6273 -O ~/.vim/project-1.4.1.tar.gz
…
$ tar xvf ~/.vim/project-1.4.1.tar.gz
plugin/project.vim
doc/project.txt
$ tar xvf project-1.4.1.tar.gz
plugin/project.vim
doc/project.txt
Notre plugin est installé !
Pour l’utiliser vous avez deux méthodes :
- Au lancement : Lancer vim avec l’option +Project
- Depuis un vim déjà en cours d’exécution avec la commande :Project
Une fois dans vim vous remarquerez une nouvelle « fenêtre » sur la gauche. C’est votre explorateur de projet qui est actuellement vide. Pour le remplir il faut utiliser la commande « \C » qui va nous posez quelques questions :
- Enter the Name of the Entry: Nom du projet que vous souhaitez ajouter à votre arbre
- Enter the Absolute Directory to Load: Chemin absolut vers votre projet comme le retourne la commande pwd
- Enter the CD parameter: Comme la question d’avant, le chemin absolut vers votre projet comme le retourne la commande pwd.
- Enter the File Filter: Une liste de masque, séparés par des virgules, selectionnant les fichiers que vous souhaiter voir apparaitre dans votre arbre. Par exemple : *.php, *.yml, *.ini, *.txt, *.css, *.js, *.xml, *.xsl
A ce moment là, vim va un peu mouliner jusqu’à trouver tout les fichiers respectant le filtre et va vous afficher votre arbre remplis sur la gauche. Une des première chose à faire est de refermer tout les « fold » avec la commande zm pour avoir une vue plus présentable. « Project » fonctionnant sur un fichier pour que votre arbre soit de nouveau là quand vous ré-ouvrirez vim faite une petite sauvegarde à l’aide de :w. Voyons maintenant une liste de commande pour se servire correctement de Project.
- [CTRL]+[w] : Changer de fenêtre. (Par exemple de l’arbre Project au document en cours d’édition)
- zo ou [Entrer] : ouvrir le dossier/fichier sous le curseur
- zc ou [Entrer] : fermer le dossier sous le curseur
- zm : fermer tout les dossier
- \R : Rafraichir le contenu du dossier courant et ses sous dossiers.
- \r : Refraichir le contenu du dossier courant.
- \g : Rechercher une expression dans le contenu des fichiers du dossier courant
- \G : Rechercher une expression dans le contenu des fichiers du dossier courant et ses sous dossiers.
- \s : Ouvre le fichier sous le curseur dans une nouvelle fenêtre horizontale
- \S : Ouvre tout les fichiers du dossier courant dans des nouvelles fenêtre horizontales.
Le folding PHP
Avec Project nous avons vu que les dossiers pouvais s’ouvrir et se fermer (normal me direz vous !), ceci s’appelle du folding. Cette fonctionnalité bien connu de tout les IDE est aussi disponible sous vim via le plugin phpfolding.vim. Je ne vous refait pas l’installation c’est toujours et encore le même principe.
A partir de maintenant vous aurez dans vos fichiers PHP un folding automatique. Voici comment s’en servir :
- zo : Ouvrir le fold courant
- zO : Ouvrir tout le fold courant et tout ses enfants
- zc : Fermer le fold courant
- zC : Fermer le fold courant et tout ses parents
- zM : Fermer tout les fold
- zj : Aller au fold suivant
- zk : Aller au fold précèdent
Si vous vous demandez encore pourquoi utiliser des tests unitaires ou encore ce que sont les tests unitaires je vous conseil vivement de vous renseigner et de revenir dans quelques minutes sur cette page !! Le web est une mine d’information infinie !!
Nous alons donc voir comment implémenter des tests unitaires en C++ avec la bibliothèque Boost qui contient entre autre la bibliothèque Boost.Test dont nous allons nous servir.
Tout d’abord il faut installer Boost. Si vous êtes sous visual studio il existe un fichier exécutable sur le site de Boost pour les distributions Linux vous devriez trouver les sources dans vos dépots.
Créez un nouveau projet « de test » qui ne sera rien d’autre qu’un projet C++ vide. Nommez le HelloWorldTest (Nom du projet à tester suivit de Test). Ceci n’est pas une obligation mais permet de se retrouver plus facilement quand on a beaucoup de projet dans un même dossier.
Ajoutez maintenant la librairie boost_unit_test_framework au liker (sous eclipse : bouton de droite sur votre projet, property, C/C++ Build, Settings, GCC C++ Linker, Librairies et ajouter boost_unit_test_framework).
Nous allons écrire notre premier fichier de tests. Pour cela créez un fichier Test.cpp (par exemple) et inscrivez dans celui ci ceci :
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
BOOST_TEST_DYN_LINK : Utiliser la bibliotheque dynamique de test de boost. (Celle que nous avons ajouter juste avant)
BOOST_TEST_MAIN : Genèrer une suite de tests principale (Master Test Suite)
Si vous compilez votre programme maintenant et que vous l’exécuter vous devriez avoir comme résultat
Test setup error: test tree is empty
Maintenant que nous avons un environnement de test fonctionnel nous allons passez à la rédaction de nos premiers tests.
Pour ceci renommer votre fichier Test.cpp en Test.h car à partir de maintenant nous l’inclurons dans tous nos fichiers de tests.
Dans votre programme à tester créez une classe Calculator avec des fonctions simples (add, sub, mul, div). Nous nous servirons de cette classe pour nos tests.
Dans votre programme de test créez un fichier CalculatorTest.cpp et incluez dans celui ci Test.h
#include « Test.h »
Nous avons besoins de faire référence à notre premier projet pour cela vous pouvez soit utiliser les fonctions de votre compilateur soit créer un lien symbolique de vos classes vers votre dossier source de test. Pour ma part, étant bien trop fainéant j’ai opté pour la deuxième solution. Mes classes étant dans le dossier Classes ceci me donne donc
ln -s ../HelloWorld/Classes/ ./
Nous rajoutons dans notre fichier CalculatorTest.cpp l’include de la classe que nous voulons tester.
#include « Classes/Calculator.h »
Et nous allons écrire un premier test !!
Pour cela nous allons utiliser plusieurs macro de Boost :
BOOST_AUTO_TEST_CASE : Qui va nous permettre de créer une « fonction virtuelle » de test
BOOST_REQUIRE_EQUAL : Qui va nous permettre de tester l’égalité d’un résultat et de retourner une valeur.
Ceci va ce présenter comme ça :
BOOST_AUTO_TEST_CASE(CalculatorAddTest1)
{
Calculator *myCalculator = new Calculator();
BOOST_REQUIRE_EQUAL(myCalculator->Add(1,2),3);//myCalculator->Add(1,2), 3);
}
Nous utilisons BOOST_AUTO_TEST_CASE pour créer une fonction de test que nous nommons CalculatorAddTest1. Nous créons un objet de type Calculator et le testons avec BOOST_REQUIRE_EQUAL.
Si vous compilez maintenant votre programme vous devriez obtenir un joli
Running 1 test case…
*** No errors detected
Il n’existe pas que BOOST_REQUIRE_EQUAL vous trouverez aussi BOOST_REQUIRE(expr), BOOST_REQUIRE_GE(left, right), BOOST_REQUIRE_GT(left, right), etc … Vous pouvez trouvez la liste de ces macros dans la documentation de Boost.
Nous avons vu comment mettre en place un projet de tests unitaires avec Boost.Test ce qui est déjà pas mal pour aujourd’hui ! Nous continurons donc plus tard
!
Pour pouvoir compiler un programme utilisant la GLib avec eclipse il vous faut configurer des options pour le compilateur et le linker
Dans Eclipse
Bouton de droite sur votre projet, propriété, C/C++ Build, Setting
Dans l’onglet Tool Settings sélectionner GCC C++ Compilateur ou GCC C Compiler suivant si vous utiliser gcc ou g++.
Dans la textbox Command line pattern ajouter
`pkg-config –cflags glib-2.0`
De même dans GCC C/C++ Linker ajouter
`pkg-config –libs glib-2.0`
Et voilà vous pouvez enfin compiler votre application !
Aujourd’hui j’ai buté sur une erreur … bête !
Si vous rencontrez ce message d’erreur
The message has expired (WSSecurityEngine: Invalid timestamp The security semantics of message have expired)
Vérifier le réglage de l’heure de vos serveurs ! En effet, c’est certainement dû à un décalage beaucoup trop grand entre l’heure de votre serveur et votre client !
Bonne Prog
PS : Utiliser NTP !
Dans la documentation officielle il est dit :
51.2.1. Alnum
Retourne true si et seulement si $value contient seulement des caractères alphabétiques et numériques. Ce validateur inclue une option permettant la validation possible des caractères espace.
51.2.2. AlphaRetourne true si et seulement si $value contient seulement des caractères alphabétiques. Ce validateur inclue une option permettant la validation possible des caractères espace.
Mais il n’est pas dit comment faire ! Alors voila comment faire :
->addValidator(‘Alnum’, false, array(‘allowWhiteSpace’ => true));
Bonne validation
Si vous souhaitez comme moi modifier un mot de passe utilisateur LDAP via un script PHP il vous faudra calculer le hach de son mot de passe. Un simple md5() ne suffisant voici la syntaxe à employer :
$newPassword = ‘{md5}’ . base64_encode(pack(‘H*’, md5($password)));
Il se peut que vous rencontriez une erreur de type :
Select query cannot join with another table in /var/www/ etc …
Ceci est du à Zend Framework qui n’autorise pas par défaut de faire une simple jointure sur une table sous jacente.
L’objet Zend_Db_Table_Select est destiné à sélectionner des données sur une table précise. Des jointures peuvent être faites, mais il n’est pas possible de sélectionner des colonnes ne faisant pas partie de la table sous jacente. Cependant, ceci aurait pu être utile dans certains cas, et l’objet Zend_Db_Table_Select possède une clause spéciale déverrouillant cette limitation. Passez la valeur false à sa méthode setIntegrityCheck. Il est alors possible de sélectionner des colonnes hors table. Attention toutefois, l’objet row/rowset résultant sera verrouillé. Impossible d’y appeler save(), delete() ou même d’affecter une valeur à certains de ses champs. Une exception sera systématiquement levée.
Pour enlever cette protection vous devez spécifier setIntegrityCheck(false) dans votre requête.
Par exemple pour une classe simple de récupération de news j’ai :
<?php/**
* News
*
* @author Lermit
* @version 1
*/require_once ‘Zend/Db/Table/Abstract.php’;
class News extends Zend_Db_Table_Abstract {
protected $_name = ‘news’;
protected $_primary = ‘news_id’;
protected $_dependentTables = array(« Users »);
protected $_referenceMap = array(
’Reporter’ => array(
’columns’ => ‘user_id’,
’refTableClass’ => ‘Users’,
’refColumns’ => ‘user_id’
)
);/**
* getLast
* retourne les $numberOfNews dernières news à partir de $start
* @author lermit
* @version 1
* @param $numberOfNews nombre de news
* @param $start à partir de la n-ieme news
* @return les news
*/
public function getLast($numberOfNews,$start)
{
$select = $this->select()
->setIntegrityCheck(false)
->from( array(‘n’ => $this->_name), array(‘text’,'date’,'user_id’))
->join(array(‘u’ =>’users’),’u.user_id=n.user_id’,'login’)
->order(‘date DESC’)
->limit($numberOfNews,$start);return $this->fetchAll($select);
}
}
Tout d’abord je spécifie le nom et la clef primaire de ma table puis les relations de jointure avec les autres tables.
$_dependentTable = tableau de la/les classe(s) de la(des) table(s) dépendante(s).
$_referenceMap = tableau de tableaux de dépendances. Chaque dépendance est listée sous la forme d’un tableau construisant comme suit :
‘columns’ => ‘colonne de la classe courante’,
‘refTableClass’ => ‘classe de la table à joindre’,
‘refColumns’ => ‘colonne de la table à joindre’
Bref ma requête utilise bien ->setIntegrityCheck(false) ce qui m’enlèvera cette fâcheuse erreur !!

BabyWadi, Blog d'information sur votre bébé
GeekInfos
M2ENV : Multi Environment Enhanced Network View
