IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Zend_Db PHP Discussion :

Manipulation de dépendances inter-tables


Sujet :

Zend_Db PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert Avatar de Madfrix
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    2 326
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 326
    Par défaut Manipulation de dépendances inter-tables
    Bonjour, je m'entraine à manipuler les méthodes findDependentRowset, findParentRow et findManyToManyRowset.

    Dans ce but j'ai construis ce petit modèle :

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    CREATE TABLE IF NOT EXISTS `personnes` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `nom` varchar(50) NOT NULL,
      `prenom` varchar(50) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
     
     
    INSERT INTO `personnes` (`id`, `nom`, `prenom`) VALUES
    (2, 'nom1', 'prenom1'),
    (3, 'nom2', 'prenom2');
     
     
    CREATE TABLE IF NOT EXISTS `livres` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `id_personne` int(11) NOT NULL,
      `nom` varchar(50) NOT NULL,
      PRIMARY KEY (`id`),
      KEY `id_personne` (`id_personne`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
     
     
    INSERT INTO `livres` (`id`, `id_personne`, `nom`) VALUES
    (2, 2, 'livre php'),
    (3, 3, 'livre java'),
    (4, 2, 'livre C');
     
    ALTER TABLE `livres`
      ADD CONSTRAINT `livres_ibfk_1` FOREIGN KEY (`id_personne`) REFERENCES `personnes` (`id`) ON DELETE CASCADE;

    Mon bootstrap contient entre autres ces 2 méthodes :

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
     protected function _initDb() {
            $db = $this->getPluginResource('db')->getDbAdapter();
            $db->setFetchMode(Zend_Db::FETCH_OBJ);
            Zend_Db_Table_Abstract::setDefaultAdapter($db);
            return $db;
        }
     
        protected function _initAutoLoader() {
            $autoLoader = new Zend_Loader_Autoloader_Resource(array(
                        'BasePath' => APPLICATION_PATH,
                        'namespace' => 'Sim'
                    ));
     
            $autoLoader->addResourceType('db', 'models/tables', 'Table');
     
            return $autoLoader;
        }

    J'ai également crée 2 modèles pour mes tables que j'ai défini ainsi :

    Table Personnes :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    class Sim_Table_Personnes extends Zend_Db_Table_Abstract {
     
        protected $_name = 'personnes';
        protected $_primary = 'id';
        protected $_dependentTables = array('Sim_Table_Livres');
     
        public function getPersonnes() {
            $select = $this->select();
            return $this->fetchAll($select);
        }
     
        public function getDependantLivres() {
            return $this->find(2)->current()->findDependentRowset('Sim_Table_Livres');
        }
     
    }


    Table Livres:
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    class Sim_Table_Livres extends Zend_Db_Table_Abstract {
     
        protected $_name = 'livres';
        protected $_primary = 'id';
        protected $_referenceMap = array(
            'relation' => array(
                'columns' => array('id_personne'),
                'refTableClass' => 'Sim_Table_Personnes',
                'refColumns' => array('id')
            )
        );
     
        public function getParentPersonne() {
            return $this->find(2)->current()->findParentRow('Sim_Table_Personnes');
        }
     
    }

    Pour finir j'ai crée 2 controllers Personnes et Livres ainsi qu'une action list listant respectivement tous les livres de la personne ayant l'id 2 et la personne qui est le lecteur du livre dont l'id est 2 (exemple un peu triviaux mais bon...)

    Pour mon cas 1, c'est bon :

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      public function listAction()
        {
            $personnes = new Sim_Table_Personnes();
            $this->view->livres = $personnes->getDependantLivres();
        }

    Ma vue récupère bien mes livres correspondant à l'id 2. Par contre dans le cas 2, j n'arrive pas à remonter au lecteur connaissant l'id d'un livre, j'ai cette erreur :

    Notice: Trying to get property of non-object in C:\wamp\www\zftable\application\views\scripts\livres\list.phtml on line 4
    Ma vue est la suivante :


    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    foreach($this->personne as $pers)
          echo $pers->nom;

    et mon action est la suivante :

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     public function listAction()
        {
            $livres = new Sim_Table_Livres();
            $this->view->personne = $livres->getParentPersonne();
        }


    Je pense pas que ce soit grand chose, mais ca me turlupine...d'autant plus que le cas de récupérer les livres connaissant le lecteur (cas inverse donc) marche parfaitement...

    Petite question subsidaire ( ) :

    Comment faire pour récupérer que certains champs en utilisant un find() ?


    Merci et désolé pour mon explication "usine à gaz"


    EDIT: info complémentaire : un print_r($this->personne) m'informe que je récupére bien l'enrgistrement (2, nom1, prenom1) mais je n'arrive pas à fetcher en objet comme dans le cas 1 et je vois pas pourquoi...

  2. #2
    Membre chevronné Avatar de manuscle
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2004
    Messages
    488
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2004
    Messages : 488
    Par défaut
    Salut!

    Normalement quand tu fait un getParentQuelquechose tu n'est pas censé récupérer un RowSet mais un Row.

    De plus, le fonction getParent[nomDeTaTable] est une methode magique de ta classe de table, tu n'a juste qu'à faire getParentSim_Table_Personnes() ou getParentRow('Sim_Table_Personnes')

    Essaie ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    // Action
     
     public function listAction()
        {
            $livres = new Sim_Table_Livres();
            $this->view->livre = $livres->find(2)->current();
            $this->view->personne = $livres->getParentSim_Table_Personnes();
        }
     
    // Vue
    echo $this->personne->nom;

  3. #3
    Membre Expert Avatar de Madfrix
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    2 326
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 326
    Par défaut
    Salut et merci de t'intéresser à mon soucis

    Citation Envoyé par manuscle Voir le message
    Normalement quand tu fait un getParentQuelquechose tu n'est pas censé récupérer un RowSet mais un Row.
    Mais un objet de type row doit pouvoir se fetcher comme un objet non ? Mon bootstrap ne paramètre pas cela comme ca par défaut ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    protected function _initDb() {
            $db = $this->getPluginResource('db')->getDbAdapter();
            $db->setFetchMode(Zend_Db::FETCH_OBJ);
            Zend_Db_Table_Abstract::setDefaultAdapter($db);
            return $db;
        }
    je sais que ton code doit marcher (vu qu'une fois je l'avais fait marcher via un tuto), mais j'arrive pas à le faire marcher maintenant :

    Fatal error: Call to undefined method Sim_Table_Livres::getParentSim_Table_Personnes() in C:\wamp\www\zftable\application\models\tables\Livres.php on line 19
    Mais bon dans la mesure du possible je souhaite passer par les fonctions "classiques" et pas "magiques"

  4. #4
    Membre chevronné Avatar de manuscle
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2004
    Messages
    488
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2004
    Messages : 488
    Par défaut
    Je ne sais pas pourquoi tu fait une fonction _initDb dans ton bootstrap, normalement si tu utilise Zend_Application tu devrais avoir ce genre de config dans application.ini :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    ;; DATABASE
    resources.db.params.charset        = utf8
    resources.db.adapter               = "pdo_mysql"
    resources.db.params.host           = "127.0.0.1"
    resources.db.params.username       = "*****"
    resources.db.params.password       = "*****"
    resources.db.params.dbname         = "*****"
    resources.db.params.date_format    = "YYYY-MM-ddTHH:mm:ss"
    resources.db.isDefaultTableAdapter = true
    Peut-etre est-il possible d'ajouter le parametre setFetchMode (voir la doc) , d'ailleur je ne savais même pas que l'on pouvait le définir, tu m'apprend quelque chose! lol

    C'est peut etre ce parametre aussi qui pose probleme, essaie de l'enlever pour voir.... Moi je ne l'utilise pas et tout va bien....

    Enfin bref toujours est-il que normalement ça devrait marcher...... je ne comprend pas.
    Car chez moi lorsque je fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $livre = $livres->find(2)->current();
    J'obtiens bien un Objet Zend_Db_Table_Row, donc je suis en mesure de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $personne = $livre->findParentRow('Sim_Table_Personnes');
    Que te renvoi le dump de ton row livre?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
            $livres = new Sim_Table_Livres();
            $this->view->livre = $livres->find(2)->current();
            Zend_Debug::dump($this->view->livre);

  5. #5
    Membre Expert Avatar de Madfrix
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    2 326
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 326
    Par défaut
    J'avoue me perdre un peu dans toutes les méthodes de récupération de données avec Zend à force de lire les tutos

    Par exemple, une requête de ce type :

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $result = $db->fetchRow('SELECT id, name FROM membres WHERE country = :country', array('country'=>'France');

    est-elle protégée finalement ?

    Autre question : une requête comme ceci ne sert juste qu'à éviter de taper la requête entièrement finalement, pas d'autre intérêt ?

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
    $select = $db->select(); // récupération de notre objet de Zend_Db_Select
    // équivalent à $select = new Zend_Db_Select($db);
    $select->from('membres',array('id','name'));
    $select->where('country = ?','usa');
    $select->order('name ASC');
    $select->limit(2);
    $result = $db->fetchAll($select);

    Au final, je suis en train de me demander si les méthodes de type findDependantRowset, findParentRow ont un véritable intérêt : pourquoi ne pas écrire manuellement la requête je pense que ces méthodes rajoutent des couches supplémentaires et sont plus longues non ? Un prepare/exec serait il pas plus rapide ?

    Merci

  6. #6
    Membre chevronné Avatar de manuscle
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2004
    Messages
    488
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2004
    Messages : 488
    Par défaut
    Pfiou! La question que tu me pose nécessiterais un tuto pour te répondre!
    Oh non, pas encore un tuto!

    Par exemple, une requête de ce type est-elle protégée finalement ?
    Zend_Db_Mysql utilise l'extension PHP PDO, donc utiliser des requêtes préparées élimine le risque d'injection SQL et accélère les performances

    Au final, je suis en train de me demander si les méthodes de type findDependantRowset, findParentRow ont un véritable intérêt : pourquoi ne pas écrire manuellement la requête je pense que ces méthodes rajoutent des couches supplémentaires et sont plus longues non ? Un prepare/exec serait il pas plus rapide ?
    ça tu le découvrira à la pratique.... Zend_Db_Table est vraiment pratique et mérite que tu te prenne la tête dessus.
    Sinon je suis d'accord avec toi dans le sens où apprendre à maitriser Zend_Db_Table n'est pas chose simple au début... Moi quand j'ai appris ZF je l'ai appris en même temps que j'ai appris la POO, c'est dire les journées, soirées, nuits même à me faire des noeuds au cerveau parce que je pigeais que dalle à tout ça!

    Ce qu'il faut comprendre dans les grandes lignes, c'est que Zend_Db_Table te permet deux choses principales:
    1. D'avoir un jeux de résultats, RowSet. Le RowSet étant un Objet issue de Zend_Db_Table_Rowset_Abstract, lui-même contenant diverses méthodes utiles

    2.Chaque ligne de résultat est un Row. Le Row étant un objet issu de Zend_Db_Table_Row_Abstract, lui-même contenant diverses methodes utiles

    L'avantage d'utiliser les résultats sous forme d'objet est que les classes contiennent des méthodes permettant de réaliser des actions de manière simple (ah bon? lol) et rapide.
    ça permet de coder plus rapidement.
    ça permet aussi plein d'autres choses que des développeurs plus chevronnés que moi t'expliquerons.

    Prenons un exemple simple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    $TMembres = new Table_membres();
    // Je veux tout les membres
    $membres = $TMembres->fetchAll(); // J'obtiens un Rowset
    // Je veux tout les Français
    $membres = $TMembres->fetchAll(array('pays' => 'fr'); // J'obtiens un Rowset
    $membre = $TMembres->fetchRow(array('pays' => 'fr'); // J'obtiens un Row 
    // car je demande tout les Français mais je ne veux récupérer que le premier résultat, donc le premier membre dans le résultat de la requete.
     
    // Je tout les membres dont l'id = 5
    $membre = $TMembres->find(5); // Rowset
     
    // Je veux LE membre n°5
    $membre = $TMembres->find(5)->current(); // Row
    // Je veux le suivant
    $membre = $TMembres->find(5)->next(); // Row
     
    // Je veux la liste des adresses du membre 5
    $adresses = $membre->findDependantRowSet('Table_Adresses'); // RowSet
    // ou 
    $adresses = $membre->findTable_Adresses(); // RowSet
    Maintenant là où ça craint, c'est ce genre de chose
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
     
    // Je veux tout les membres ainsi que leurs adresses
    $membres = $TMembres->fetchAll(); // J'obtiens un Rowset
     
    foreach ($membres as $membre) {
        $adresses = $membre->findTable_Adresses();
    }
    // Car dans cette boucle tu fait une requete à chaque changement de membre
    // La simple requete avec jointure est plus apropriée
     
    //EDIT: A partir de là ça craint plus
    // Le fait d'utiliser l'objet est que c'est facile d'ajouter des parametres dans ta requete:
     
    $select = $db->select(); 
    $select->from('membres',array('id','name'));
    $select->where('country = ?','usa');
    $select->order('name ASC');
    // Je peux faire cela par exemple, je suis pas admin, j'ai pas le droit de voir les admins
    if(Zend_Auth::getInstance()->getIdentity()->isAdmin == 0) {
    $select->where('is_admin', 0);
    }
     
    $result = $db->fetchAll($select);
    Bref, à toi de choisir ce qui conviens le mieux à ton application... il n'y a pas de regle.

Discussions similaires

  1. manipulation de partitions sur table
    Par debdba dans le forum Administration
    Réponses: 7
    Dernier message: 13/02/2008, 10h09
  2. Problème de Trigger inter-table
    Par baptx dans le forum PL/SQL
    Réponses: 7
    Dernier message: 24/05/2007, 17h19
  3. Manipulation de champs de table
    Par beberd dans le forum SQL Procédural
    Réponses: 1
    Dernier message: 27/12/2006, 13h05
  4. [MySQL] Suppression avec contrôle de lien inter-tables
    Par lodan dans le forum PHP & Base de données
    Réponses: 7
    Dernier message: 29/07/2006, 17h35
  5. Probleme de liaison inter table
    Par capejere dans le forum Requêtes
    Réponses: 7
    Dernier message: 03/07/2006, 11h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo