Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
bonjour,
j'aimerais savoir comment peut on faire une requete avec un IN imbriqué?
car dans la doc je n'ai pas vu d'exemple...
par exemple, j'ai ceci en sql:
select v.nom, v.description from ville v, pays p, ville_in_pays vp where pays like '$pays' and v.id_ville=vp.id_ville and vp.id_pays=p.id_pays and v.id_ville IN (select recompense.id_ville from recompense)
Merci d'avance de votre aide
Hors ligne
Salut,
Avant de t'aider, j'aimerais juste savoir où se situe réellement ton problème.
Tu ne sais pas comment créer une requête à l'aide de Zend_Db ou tu ne sais pas comment créer une sous-requête dans ton "IN()" ?
Remarques : au lieu d'utiliser des conditions comme celle-ci "v.id_ville=vp.id_ville and vp.id_pays=p.id_pays", utilises des jointures
Dernière modification par acharrex (14-10-2008 21:02:19)
Hors ligne
M'enfin, voici déjà une solution :
$select = $this->_db->select() ->from("ville", array("nom", "description")) ->join("ville_in_pays", "ville_in_pays.id_ville = ville.id_ville", array()) ->join("pays", "pays.id_pays = ville_in_pays.id_pays", array()) ->where("ville.id_ville IN (".new Zend_Db_Expr($this->_db->select()->from("recompense", array("id_ville"))).")") ->where("pays.pays_name LIKE '{$pays}'") ->query(); echo '<pre>'; print_r($select->fetchAll()); echo '</pre>';
Dernière modification par acharrex (14-10-2008 21:15:48)
Hors ligne
acharrex a écrit:
M'enfin, voici déjà une solution :
Code:
$select = $this->_db->select() ->from("ville", array("nom", "description")) ->join("ville_in_pays", "ville_in_pays.id_ville = ville.id_ville", array()) ->join("pays", "pays.id_pays = ville_in_pays.id_pays", array()) ->where("ville.id_ville IN (".new Zend_Db_Expr($this->_db->select()->from("recompense", array("id_ville"))).")") ->where("pays.pays_name LIKE '{$pays}'") ->query(); echo '<pre>'; print_r($select->fetchAll()); echo '</pre>';
j'ai essayé ce code là,
avec $this->_db->getAdapter()->select()
il me renvoie
Catchable fatal error: Object of class AnalyserController could not be converted to string in controller.php
ey si je met avec $this->_db->select()
il renvoie:
Exception : Zend_Db_Statement_Exception Message : SQLSTATE[42000]: Syntax error or access violation: 1065 Query was empty
Si quelqu'un pourrait me dire pourquoi ma requête ne fonctionne pas, ça maiderait bcp
Merci d'avance!
Hors ligne
Salut,
Soit tu utilises _db, soit tu utilises getAdapter(), mais pas les deux puisque getAdapter() sert à récupérer l'objet 'db' par défaut.
Donc c'est logique que la première syntaxe ne fonctionne pas.
Ensuite pour l'autre message d'erreur, est-ce que tu peux nous coller le code de ton select() en entier ?
A+ benjamin.
Hors ligne
j'ai fait un autre test avec une requete
et j'ai le probleme chaque fois que j'essaye de nommer une table par exemple quand je fait:
->from(array('v' => $this->ville), array('v.id_ville', 'v.nom_ville')) ->where('v.id_ville= ?', $this->identifiant)
là il me met:
Exception : Zend_Db_Statement_Exception Message : SQLSTATE[42000]: Syntax error or access violation: 1065 Query was empty
par contre quand je met
->from($this->ville, array('id_ville', 'nom_ville'))) ->where('id_ville= ?', $this->identifiant)
ça fonctionne... :s
Quelqu'un sait-il pourquoi?
car quand je vais faire une jointure, je devrai nommer mes tables car certaines auront les même champs
merci d'avance
edit: ajout de la parenthèse manquante
Dernière modification par Fly706 (15-10-2008 12:03:13)
Hors ligne
C'est plutôt :
->from(array('v' => $this->ville), array('v.id_ville', 'v.nom_ville')) ->where('v.id_ville= ?', $this->identifiant)
Hors ligne
oui j'ai oublié une parenthèse :s
mais le problème reste le même...
Hors ligne
Qu'est-ce qu'est censé te renvoyer
$this->ville
?
Hors ligne
Voici le code du modèle que tu devrais utiliser :
class Ville extends Zend_Db_Table { protected $_name = 'ville'; protected $_primary = 'id_ville'; //...
Et là-dedans tu mets une fonction dans laquelle tu fais ta requête :
$select = $this->_db->select() ->from(array("v" => $this->_name), array("nom", "description")) ->where("v.{$this->_primary} = ?", $this->identifiant) ->query();
Hors ligne
Voilà
D'où ma question, ce '$this->ville' ne me plaisait pas...
Hors ligne
mon modèle ville, je l'avais déjà.
dans mon controlleur, j'ai:
public function init() { parent::init(); $request = $this->getRequest(); try { $this->ville= new Ville(array('db' => 'db')); } catch (Zend_Exception $e) { throw($e); } }
puis j'ai ma fonction...
et tjs le problème de:
Exception : Zend_Db_Statement_Exception Message : SQLSTATE[42000]: Syntax error or access violation: 1065 Query was empty
:s
Dernière modification par Fly706 (15-10-2008 13:13:35)
Hors ligne
OK, tu peux juste poster le code de ton contrôleur et ton modèle ?
Hors ligne
mon modele, j'ai ceci:
<?php class Ville extends Zend_Db_Table_Abstract { protected $_name = 'projet_ville'; } ?>
mon controlleur:
<?php class Controller extends AbstractController { public function init() { parent::init(); $request = $this->getRequest(); try { $this->ville= new Ville(array('db' => 'db')); } catch (Zend_Exception $e) { throw($e); } } private function _getVille($donnee) { $select = $this->ville->select() ->from(array('v' => $this->ville), array('v.id_ville', 'v.nom_ville')) ->where('v.id_ville= ?', $donnee) return $this->ville->fetchAll($select)->toArray(); } public function IndexAction() { $request = $this->getRequest(); $this->identifiant= $request->getParam('identifiant'); $this->view->UneVille = $this->_getVille($this->identifiant); $this->render(); } }
quand je fais ceci, il me renvoie l'exception
et quand je fais ceci:
private function _getVille($donnee) { $select = $this->ville->select() ->from($this->ville, array('id_ville', 'nom_ville')) ->where('id_ville= ?', $donnee) return $this->ville->fetchAll($select)->toArray(); }
ça fonctionne...
Mais pour faire des jointures, j'aurai besoin de faire de nommer mes tables par des initials car des champs seront commun à plusieurs tables
merci d'avance si qqun peut m'eclairer...
Hors ligne
Oui, ok, là je vois où est ton problème.
Il faut juste que tu y mettes un peu plus d'ordre, et que tu ne trompes pas entre ton "$this->ville" instance de ton modèle ville, et du "$this->ville" contenant le nom de ta table.
Voici ce que je te propose pour ton contrôleur :
<?php class Controller extends AbstractController { public function init() { parent::init(); $request = $this->getRequest(); try { $this->ville= new Ville(); } catch (Zend_Exception $e) { throw($e); } } public function IndexAction() { $request = $this->getRequest(); $this->identifiant= $request->getParam('identifiant'); $this->view->UneVille = $this->ville->getVille($this->identifiant); $this->render(); } }
Puis pour ton modèle :
<?php class Ville extends Zend_Db_Table_Abstract { protected $_name = 'projet_ville'; protected $_primary = 'id_ville'; public function getVille($donnee) { $select = $this->_db->select() ->from(array('v' => $this->_name), array("v.{$this->_primary}", "v.nom_ville")) ->where("v.{$this->_primary} = ?", $donnee) return $select->fetchAll(); } }
Et tu peux sans problème remplacer cette requête par celle que je t'ai donné dans mon deuxième post.
Voilà, normalement, tout devrait jouer
Dernière modification par acharrex (15-10-2008 14:01:38)
Hors ligne
ce n'est pas possible de garder ma fonction dans le controlleur?
Hors ligne
Si si, mais les fonctions autres que les actions se mettent dans le modèle. Enfin, en tout cas par convention...
Et pour que dans ta fonction "getVille" tu puisses utiliser "$this->_db->select()", il faut que ta classe étende Zend_Db_Table.
Donc en mettant "getVille" dans ton modèle, tu es doublement gagnant
Hors ligne
Tu n'as aucun intérêt à placer cette méthode dans ton bootstrap, sinon tu ne réponds plus aux conventions du MVC.
Il faut placer les méthodes de tes modèles dans tes classes de modèles, sinon ça devient desuite très difficile à maintenir.
Un controller ne doit avoir un rôle que de Controller et un modèle de Modèle avec toutes ses méthodes qui le définissent et permettent l'accès à ses propres données.
A+ benjamin.
Edit : acharrex a été plus rapide
Dernière modification par Delprog (15-10-2008 14:32:50)
Hors ligne
et pour ta requete:
$select = $this->_db->select() ->from("ville", array("nom", "description")) ->join("ville_in_pays", "ville_in_pays.id_ville = ville.id_ville", array()) ->join("pays", "pays.id_pays = ville_in_pays.id_pays", array()) ->where("ville.id_ville IN (".new Zend_Db_Expr($this->_db->select()->from("recompense", array("id_ville"))).")") ->where("pays.pays_name LIKE '{$pays}'") ->query();
je la place dans le modele de ville?
car comme j'instancie les classes pays et ville_in_pays dans le "constructeur" de mon controleur, il ne les connaitra pas encore il me semble :s
il y a un truc qui m'échappe...
edit: j'ai essayé de faire comme décrit ci-dessus... il me met mnt:
Exception : Zend_Db_Select_Exception Message : Unrecognized method 'fetchAll()'
Dernière modification par Fly706 (15-10-2008 14:52:42)
Hors ligne
La classe de ton modèle doit étendre "Zend_Db_Table".
Hors ligne
acharrex a écrit:
La classe de ton modèle doit étendre "Zend_Db_Table".
oui comme dit plus haut.
j'ai bien mit : class Ville extends Zend_Db_Table mais il connait pas fetchAll :s
c'est bien comme cela?
Sinon pour ta requete, je dois la placer dans quel modele?
(car moi je l'aurais mit dans le controleur... mais comme tu as dit, c'est plus clair en la mettant dans le modele)
Hors ligne
Tu dois le placer dans ton modèle "Ville", car ce que tu souhaites c'est sélectionner des villes...
Ton modèle doit être :
<?php class Ville extends Zend_Db_Table { protected $_name = 'projet_ville'; protected $_primary = 'id_ville'; public function getVille($donnee) { $select = $this->_db->select() ->from("ville", array("nom", "description")) ->join("ville_in_pays", "ville_in_pays.id_ville = ville.id_ville", array()) ->join("pays", "pays.id_pays = ville_in_pays.id_pays", array()) ->where("ville.id_ville IN (".new Zend_Db_Expr($this->_db->select()->from("recompense", array("id_ville"))).")") ->where("pays.pays_name LIKE '{$pays}'") ->query(); echo '<pre>'; print_r($select->fetchAll()); echo '</pre>'; } }
Hors ligne
ok ok merci pour le temps consacré ;-)
une petite chose, tu dis que je dois placer ta requete dans le modele ville car je selectionne des villes...
mais si dans ma selection apres jointure, je prend le nom du pays par exemple.
je laisse tjs la fonction dans le modele ville? il reconnaitra direct le champs nom de la table pays?
Hors ligne
Salut,
Si tu fais une jointure de ce type :
->join("pays", "pays.id_pays = ville_in_pays.id_pays", array("nom"))
Il prendra automatiquement le champ "nom" de la table "pays".
Sinon, il est vrai que ta requête se basent sur plusieurs tables différentes (ville, pays, ville_in_pays, competence). Pour savoir dans quel modèle la placer (pour structurer ton programme, car en fait tu pourrais la mettre n'importe où), il faut que tu saches quel contrôleur va se charger de son appel.
Par exemple, si je veux afficher la liste des membres de mon site et y indiquer le nombre de messages écrits dans le forum, la ville dans laquelle ils habitent etc., je vais créer une requête sélectionnant tous les membres puis faisant une jointure sur la table des villes et sur celles des messages du forum.
Dans dans ce cas, ma requête sera placée dans une fonction du modèle "Liste des membres". Car mon but est de sélectionner les membres puis des informations complémentaires.
Sinon, il faut bien que tu dises que tu n'as pas besoin de créer un modèle étendant Zend_Db_Table pour chacune de tes tables. Avec le "$this->_db->select()->...", tu peux sélectionner autant de champs que tu veux dans autant de tables que tu souhaites.
Voilà, j'espère que c'est assez clair
Dernière modification par acharrex (15-10-2008 16:24:22)
Hors ligne
oui merci bcp
Hors ligne