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