lundi 15 septembre 2008

[Zend Framework] Faire un join

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 !!

6 commentaires:

  1. Merci pour cette astuce très utile.

    RépondreSupprimer
  2. Merci pour ton astuce, je viens de passer 2jours a me tirer les cheveux car je n'arrivais pas a utiliser ce Join.
    Merci encore énormément !!!

    RépondreSupprimer
  3. c un truc de dingue....
    pourquoi c pas dans la doc ???

    RépondreSupprimer
  4. "pourquoi c pas dans la doc ?"
    Je me le demande aussi !!!!


    Merci

    RépondreSupprimer
  5. Merci pour cette explication claire

    RépondreSupprimer
  6. MERCI ! J'ai perdu une après midi sur ce truc là !

    RépondreSupprimer