Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
Pages: 1
Bonjour,
J'avais l'habitude d'écrire toute mes requête, relatives à une table, dans une seul classe (qui étant Zend_Db_Table_Abstract).
Mais je souhaite être un peu plus fin.
Je vous copie le code et vous montre la où ça bloque.
class ClientController extends Zend_Controller_Action { public function init() { $this->db = new Application_Model_DbTable_Client(); } public function indexAction() { $this->view->result = $this->db->fetchAll(); //-------------erreur } public function ajouterAction() { $this->view->form = $form = new Application_Form_Client(); if($this->getRequest()->isPost()) { if($form->isValid($this->getRequest()->getPost())) { $this->db->ajouter($form->getValues()); //-------------erreur $this->_redirect('/client/index'); } else { $form->populate($this->getRequest()->getPost()); } } } }
ici, le fetchAll() me donne "Fatal error: Class name must be a valid object or a string in /usr/local/lib/ZendFramework/library/Zend/Db/Table/Row/Abstract.php on line 344"
Dans la vue il y a une boucle foreach sur le résultat, en la supprimant, l'erreur disparait.
<?php foreach($this->result as $row) : ?> <tr class="<?php echo $this->cycle(array('odd','even'))->next(); ?>"> <td><?php echo $this->escape($row->nom);?></td> <td><?php echo $this->escape($row->prenom);?></td> </tr> <?php endforeach; ?>
un <?php Zend_Debug::dump($this->result); ?> me prouve que le résultat est bien stocké dans l'attribut result.
De plus, la méthode ajouter(), me renvoie une erreur :
"Fatal error: Call to a member function insert() on a non-object in /usr/local/lib/ZendFramework/library/Zend/Db/Table/Row/Abstract.php on line 467"
Je vais maintenant vous présenter mes classes métier.
<?php class Application_Model_DbTable_Client extends Zend_Db_Table_Abstract { protected $_name = 'client'; protected $_primary = 'id'; protected $_rowClass = 'Application_Model_Client'; public function afficher() { return $this->fetchAll(); } public function trouver($id) { return $this->find($id); } public function ajouter($data) { // Ancienne méthode // $row = $this->createRow(); // $row->nom = $data['nom'] // $row->... tous les champs // $row->save(); // La façon que je désire $row = new Application_Model_Client((array)$data); $row->save(); } }
Cette classe se contente de retourner le résultat d'une requête, l'idée est de déléguer le traitement à une autre classe.
L'autre class est la suivante, elle se contenant des getter et setter et peux ajouter des méthode de traitement pour une ligne de bd : sortir des statistiques, vérifier un champs précis avant un ajout, calculer une date - ex : getDateRestante()-, etc ...
<?php class Application_Model_Client extends Zend_Db_Table_Row_Abstract { protected $id; protected $nom; protected $prenom; public function __construct(array $options = null) { if (is_array($options)) { $this->setOptions($options); } } public function setOptions(array $options) { $methods = get_class_methods($this); foreach ($options as $key => $value) { $method = 'set' . ucfirst($key); if (in_array($method, $methods)) { $this->$method($value); } } return $this; } public function __set($name, $value) { $method = 'set' . $name; if (!method_exists($this, $method)) { throw new Exception('Invalid client property'); } $this->$method($value); } public function __get($name) { $method = 'get' . $name; if (!method_exists($this, $method)) { throw new Exception('Invalid client property'); } return $this->$method(); } public function getId() { return $this->id; } public function setId($id) { $this->id = $id; return $this; } public function getNom() { return $this->nom; } public function setNom($nom) { $this->nom = $nom; return $this; } public function getPrenom() { return $this->prenom; } public function setPrenom($prenom) { $this->prenom = $prenom; return $this; } }
Les méthodes setOption, __get et __set sont inspiré du net.
L'idée est d'injecter un tableau à la classe pour qu'elle remplie les champs toute seul. Ce qui peut amener à créer une classe contenant ces 3 méthodes qui sera héritée par la suite.
Je sollicite votre aide pour m'aider à faire disparaître les erreurs cités plus haut :
les appels aux méthodes ajouter() et fetchall() (d'une façon gnéral j'ai l'impression que rien ne marche !)
Par ailleurs, si avez vous des commentaire sur l'organisation des classe je suis à votre écoute.
Hors ligne
en tout cas lorsque je fais
$dbClient = new Application_Model_DbTable_Client(); $this->view->res = $dbClient->trouver();
j'ai cette réponse
Fatal error: Class name must be a valid object or a string in /usr/local/lib/ZendFramework/library/Zend/Db/Table/Row/Abstract.php on line 344
alors si je met en commentaire le constructeur de "Application_Model_Client", cela fonctionne, mais les getters retournent une chaine vide. Les attributs étant vide pour le coups...
j'ai des le début retiré le "protected $_rowClass = 'Application_Model_Client';"
mais j'aimerais quand même séparer mes requêtes en deux classes
Hors ligne
Bonjour,
Bon déjà, je pense que ton découpage du code part mal ! Ta classe "Application_Model_Client" hérite "Zend_Db_Table_Row_Abstract" ?!? Elle devrait plutôt hériter de "Application_Model_AbstractModel"
Et ta classe "Application_Model_DbTable_Client" a du code qui, selon moi, n'a rien à faire ici. Tu devrais plutôt créer une classe "Application_Model_DbTable_ClientMapper", qui ressemblerait à quelque chose comme ça :
[lang=php] <?php class Application_Model_SprintMapper { /** * @var Zend_Db_Table_Abstract $_dbTable */ protected $_dbTable = null; protected function __construct() { $this->setDbTable( 'Application_Model_Db_Table_Client' ); } public function setDbTable( $dbTable ) { if( is_string( $dbTable ) ) $dbTable = new $dbTable(); if( !$dbTable instanceof Zend_Db_Table_Abstract ) throw new Exception('Invalid table data gateway \'' . $dbTable . '\' provided'); $this->_dbTable = $dbTable; return $this; } public function ajouter( $data ) { // Si pas d'id, c'est une insertion if( null === ( $data['id'] ) ) $this->_dbTable->insert( $data ); // Sinon, c'est une modification else $this->_dbTable->update( $data, array( 'id = ?' => $data['id'] ) ); } // Autres fonctions } ?>
Et ta classe "Application_Model_DbTable_Client" perd toutes ses fonctions, pour ne conserver que les propriétés ($_name, $_primary et $_referenceMap)
Et je t'invite à lire ce topic
Hors ligne
les erreurs retournées relèvent plus de php que de Zend:
1)tu affectes le résultat de fetchAll() sur une proprieté(en particulier $this->db) qui n'existe pas dans la classe ClientController encore moins dans sa classe parente.essaies de déclarer ta variable comme proprieté de ClientController comme ceci: private $db=null
2)l'appel de la méthode trouver devrait recevoir en paramètre un id(d'après sa signature)
---------------------------------------
maryooman a écrit:
Bonjour,
J'avais l'habitude d'écrire toute mes requête, relatives à une table, dans une seul classe (qui étant Zend_Db_Table_Abstract).
Mais je souhaite être un peu plus fin.
Je vous copie le code et vous montre la où ça bloque.Code:
class ClientController extends Zend_Controller_Action { public function init() { $this->db = new Application_Model_DbTable_Client(); } public function indexAction() { $this->view->result = $this->db->fetchAll(); //-------------erreur } public function ajouterAction() { $this->view->form = $form = new Application_Form_Client(); if($this->getRequest()->isPost()) { if($form->isValid($this->getRequest()->getPost())) { $this->db->ajouter($form->getValues()); //-------------erreur $this->_redirect('/client/index'); } else { $form->populate($this->getRequest()->getPost()); } } } }ici, le fetchAll() me donne "Fatal error: Class name must be a valid object or a string in /usr/local/lib/ZendFramework/library/Zend/Db/Table/Row/Abstract.php on line 344"
Dans la vue il y a une boucle foreach sur le résultat, en la supprimant, l'erreur disparait.Code:
<?php foreach($this->result as $row) : ?> <tr class="<?php echo $this->cycle(array('odd','even'))->next(); ?>"> <td><?php echo $this->escape($row->nom);?></td> <td><?php echo $this->escape($row->prenom);?></td> </tr> <?php endforeach; ?>un <?php Zend_Debug::dump($this->result); ?> me prouve que le résultat est bien stocké dans l'attribut result.
De plus, la méthode ajouter(), me renvoie une erreur :
"Fatal error: Call to a member function insert() on a non-object in /usr/local/lib/ZendFramework/library/Zend/Db/Table/Row/Abstract.php on line 467"
Je vais maintenant vous présenter mes classes métier.Code:
<?php class Application_Model_DbTable_Client extends Zend_Db_Table_Abstract { protected $_name = 'client'; protected $_primary = 'id'; protected $_rowClass = 'Application_Model_Client'; public function afficher() { return $this->fetchAll(); } public function trouver($id) { return $this->find($id); } public function ajouter($data) { // Ancienne méthode // $row = $this->createRow(); // $row->nom = $data['nom'] // $row->... tous les champs // $row->save(); // La façon que je désire $row = new Application_Model_Client((array)$data); $row->save(); } }Cette classe se contente de retourner le résultat d'une requête, l'idée est de déléguer le traitement à une autre classe.
L'autre class est la suivante, elle se contenant des getter et setter et peux ajouter des méthode de traitement pour une ligne de bd : sortir des statistiques, vérifier un champs précis avant un ajout, calculer une date - ex : getDateRestante()-, etc ...Code:
<?php class Application_Model_Client extends Zend_Db_Table_Row_Abstract { protected $id; protected $nom; protected $prenom; public function __construct(array $options = null) { if (is_array($options)) { $this->setOptions($options); } } public function setOptions(array $options) { $methods = get_class_methods($this); foreach ($options as $key => $value) { $method = 'set' . ucfirst($key); if (in_array($method, $methods)) { $this->$method($value); } } return $this; } public function __set($name, $value) { $method = 'set' . $name; if (!method_exists($this, $method)) { throw new Exception('Invalid client property'); } $this->$method($value); } public function __get($name) { $method = 'get' . $name; if (!method_exists($this, $method)) { throw new Exception('Invalid client property'); } return $this->$method(); } public function getId() { return $this->id; } public function setId($id) { $this->id = $id; return $this; } public function getNom() { return $this->nom; } public function setNom($nom) { $this->nom = $nom; return $this; } public function getPrenom() { return $this->prenom; } public function setPrenom($prenom) { $this->prenom = $prenom; return $this; } }Les méthodes setOption, __get et __set sont inspiré du net.
L'idée est d'injecter un tableau à la classe pour qu'elle remplie les champs toute seul. Ce qui peut amener à créer une classe contenant ces 3 méthodes qui sera héritée par la suite.
Je sollicite votre aide pour m'aider à faire disparaître les erreurs cités plus haut :
les appels aux méthodes ajouter() et fetchall() (d'une façon gnéral j'ai l'impression que rien ne marche !)
Par ailleurs, si avez vous des commentaire sur l'organisation des classe je suis à votre écoute.
Hors ligne
Bonjour,
J'ai modifié le constructeur et les méthodes __get et __set de la classe model_Client.
<?php class Application_Model_Client extends Zend_Db_Table_Rowset_Abstract { protected $id; protected $nom; protected $prenom; public function __construct(array $options = null) { parent::__construct($options); if (is_array($options)) { $this->setOptions($options); } } public function setOptions(array $options) { $methods = get_class_methods($this); foreach ($options as $key => $value) { $method = 'set' . ucfirst($key); if (in_array($method, $methods)) { $this->$method($value); } } return $this; } public function getId() { return $this->id; } public function setId($id) { $this->id = $id; return $this; } public function getNom() { return $this->nom; } public function setNom($nom) { $this->nom = $nom; return $this; } public function getPrenom() { return $this->prenom; } public function setPrenom($prenom) { $this->prenom = $prenom; return $this; } public function __set($name, $value) { $res = explode('_', $name); $name = $res[1]; $method = 'set' . $name; if (!method_exists($this, $method)) { throw new Exception('Invalid client property'); } $this->$method($value); } public function __get($name) { $res = explode('_', $name); $name = $res[1]; $method = 'get' . $name; if (!method_exists($this, $method)) { throw new Exception($name); } return $this->$method(); } }
Et voici la classe Model_DbTable_Client
Je ne souhaite pas utiliser une table Mapper, vu le peux de code, autant tout mettre ensemble
<?php class Application_Model_DbTable_Client extends Zend_Db_Table_Abstract { protected $_name = 'client'; protected $_primary = 'client_id'; protected $_rowClass = 'Application_Model_Client'; public function afficher() { return $this->fetchAll(); } public function trouver($id) { return $this->fetchAll('client_id = ' . $id); } public function ajouter($data) { $row = $data; unset($row['client_id']); return $this->insert($row); } public function modifier($id,$data) { return $this->update($data, 'client_id = ' . $id); } public function supprimer($id) { $this->delete('client_id = ' . $id); }
Avec un 'Zend_Debug::dump($res)
la requete à eu lieu
Cepandant, il y a une erreur étrange
Je ne peut pas itérer les résultats !
An error occurred
Application error
Exception information:
Message: Data for provided position does not exist
Stack trace:
#0 /usr/local/lib/ZendFramework/library/Zend/Db/Table/Rowset/Abstract.php(249): Zend_Db_Table_Rowset_Abstract->_loadAndReturnRow(0)
#1 /usr/local/lib/ZendFramework/library/Zend/Db/Table/Rowset/Abstract.php(202): Zend_Db_Table_Rowset_Abstract->current()
Je ne peux pas utiliser un foreach, ni utiliser les méthodes getRow(int) ou current()....
Hors ligne
Pages: 1