Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 14-06-2011 21:50:48

maryooman
Membre
Date d'inscription: 15-02-2010
Messages: 106

lors de save() : Call to a member function insert() on a non-objec

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

 

#2 21-06-2011 13:01:58

maryooman
Membre
Date d'inscription: 15-02-2010
Messages: 106

Re: lors de save() : Call to a member function insert() on a non-objec

en tout cas lorsque je fais

Code:

$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

 

#3 21-06-2011 14:49:28

f.garoby
Membre
Date d'inscription: 02-03-2011
Messages: 105

Re: lors de save() : Call to a member function insert() on a non-objec

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 :

Code:

[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

 

#4 22-06-2011 01:55:53

amiss
Membre
Lieu: Cesson-Sévigné
Date d'inscription: 08-05-2011
Messages: 115

Re: lors de save() : Call to a member function insert() on a non-objec

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

 

#5 20-07-2011 16:34:34

maryooman
Membre
Date d'inscription: 15-02-2010
Messages: 106

Re: lors de save() : Call to a member function insert() on a non-objec

Bonjour,

J'ai modifié le constructeur et les méthodes __get et __set de la classe model_Client.

Code:

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

Code:

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

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages