Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
Bonsoir,
Je me suis lancé dans l'utilisation de JSON avec le Zend_Json. J'ai écrit cette action qui ne fait que répondre à une requête Ajax :
*/ public function bardescAction() { if ($this->_request->isXmlHttpRequest()) // Appel Ajax { $this->_helper->layout->disableLayout(); $this->_helper->viewRenderer->setNoRender(); $batiments = new Batiments(); if ($this->_request->isGet()) { $position = $this->_request->getParam('position'); $batiment = $batiments->getBatiment($position)->toArray(); $json = Zend_Json::encode($batiment); echo $json; // La réponse me parvient en javascript par eval('(' + o.responseText + ')'); /* $this->_response->setHeader('Content-Type', 'text/x-json; charset=UTF-8') ->setBody($json); $this->_response->sendResponse(); */ } } else { $this->_helper->redirector('index', 'index'); } }
Cette action fonctionne, mais il paraît que ce n'est pas bien de renvoyer la réponse par un echo dans le contrôleur ? Je ne dois pas savoir m'y prendre, car si je remplace l'echo par le code en commentaires, j'obtiens une erreur "missing ) in parenthetical"...
Quelle est la bonne méthode ?
Merci pour vos conseils...
Hors ligne
Bonjour, l'alternative est d'utiliser les contextes, cela simplifiera ce code, car le framework peut faire cela en partie : ca affiche une vue ajax (bardesc.json par exemple) suivant le contexte ajax ou normal ou +.
http://framework.zend.com/manual/fr/zen … lpers.html
Hors ligne
Merci fte, apparemment c'est bien ce qu'il me faut
Par contre je n'ai pas très bien compris comment s'utilisent les contextes, pourrais-tu me montrer ce que ça donne avec mon action ? Car je n'ai pas de vue "bardesc" (d'où le setNoRender), et je ne trouve pas comment envoyer le tableau $batiment avec les contextes...
Hors ligne
j'ai moi aussi travaillé dans cette voie
<?php Zend_Loader::loadClass("Application_Controllers_Action"); class Application_Controllers_Json extends Application_Controllers_Action { protected $_useHistory = false; /** * initialise le controleur * tout les controleur ajax ne retourne pas de vue * ils envoient du json au client */ public function init() { parent::init(); $this->getFrontController()->setParam('noViewRenderer', true); if ($this->_request->isXmlHttpRequest()) { $this->_response->setHeader('Content-Type', 'application/json; charset=UTF-8', true); } else { // on envoie la reponse en texte lors d'une invocation via le navigateur // cela permet de tester la réponse. $this->_response->setHeader('Content-Type', 'text/plain; charset=UTF-8', true); } $this->response = array(); } public function postDispatch() { Zend_Loader::loadClass('Zend_Json_Encoder'); echo utf8_encode(ereg_replace('"__className":"[^\"]+",', '',Zend_Json_Encoder::encode($this->response))); parent::postDispatch(); } }
Application_Controllers_Action est une classe commune à tous mes contrôleur sans utilité ici. elle dérive simplement de Zend_Controller_Action
pour utiliser
Application_Controllers_Json
il suffit de faire dériver son contrôleur de celle-ci en lieu et place de Zend_Controller_Action.
tout comme un contrôleur utilise $this->view celui-ci utilise $this->response.
il suffit d'ajouter des membres à $this->response pour qu'il soient envoyé au client.
au passage je supprime les membres __className de l'objet car il ne sont pas utile en JSON et j'encode en UTF8 car XMLHttpRequest attends de l'UTF8 par défaut
un exemple
<?php Zend_Loader::loadClass("Application_Controllers_Json "); class SiteController extends Application_Controllers_Json { /** * GetAll retourne la liste de tout les sites disponibles pour les stat * c'est adire tous les sites sauf ceux déjà soucrits et pour lesquels la demande à déja * ete faite. la liste est paginée * * @param start curseur de départ de la page * @param limit nombre d'élément à retourner * @param sort attribut à utiliser pour le tri * @param dir direction du tri * * @see getOrder * @see getBasket */ public function getAllAction() { /* params : start=96 limit=24 sort=site_name dir=DESC */ $user = Zend_Auth::getInstance()->getIdentity(); $userid = $user->usr_id; $data = $this->model->getDispoListByUserId($userid); $this->_setListResponse($data); } /** * GetOrder retourne la liste de tout les sites déjà soucrits * * @param sort attribut à utiliser pour le tri * @param dir direction du tri * * @see getAll * @see getBasket */ public function getOrderAction() { $user = Zend_Auth::getInstance()->getIdentity(); $userid = $user->usr_id; $data = $this->model->getSiteListByUserId($userid, true); $this->_setListResponse($data); } /** * GetBascket retourne la liste de tout les sites pour lesquels la demande a * ete faite. * * @param sort attribut à utiliser pour le tri * @param dir direction du tri * * @see getOrder * @see getAll */ public function getBasketAction() { $user = Zend_Auth::getInstance()->getIdentity(); $userid = $user->usr_id; $data = $this->model->getAccessListByUserId($userid); $this->_setListResponse($data); } ... protected function _setListResponse($data) { if ($data) { $this->response = array( 'success' => true, 'results' =>count($data), 'rows'=> $data ); } else { $this->response = array( 'success' => false ); } } }
j'en fais un gros usage en ce moment une grosse appli tout en Ajax.
9 contrôleurs au total 1 contrôleur standard qui retourne l'interface utilisateur et quelque bricoles et 8 contrôleurs qui ne font que du JSON
A+JYT
PS: je suis en ZF 1.0.4
Hors ligne
Bonjour,
@sekaijin :
Merci pour tes exemples complets et bien écrit. J'ai cependant quelques questions de débutant (?!?):
- Pourquoi ne pas utiliser un helper d'action pour la méthode _setListResponse() ? de cette façon, n'est-il pas plus simple d'y accéder à partir de tous les contrôleurs ?
- Je me pose également la question de savoir pourquoi la version de ZF que tu utilise est la 1.0.4. Quelles en sont les raisons ? problèmes de mise à jour (compatibilité avec l'existant) ? C'est sans intérêt pour ton projet ? ...
a+, Roulio
Dernière modification par Roulio (29-10-2008 09:31:24)
Hors ligne
pourquoi pas mais je n'en ai pas besoin dans tous mes contrôleurs la plus part ne retournent pas de liste
je vais avoir par exemple un membre par objet retourné
$this->response = array( 'success' => true, 'user' =>$user, 'profile'=> $profile, 'lang' => 'en' );
J'ai pour habitude de toujours mettre un membre success à true ou false.
en cas de false j'ajoute aussi souvent un membre errors qui est une liste d'objet error qui contienne un code et un message. le message sert à débuger le code lui sert à l'application pour afficher un message local (traitement coté client des erreurs localisé)
A+JYT
je suis en 1.0.4 pour des raison de compatibilité php sur mes hébergements qui n'ont pas évolués.
Dernière modification par sekaijin (29-10-2008 11:48:01)
Hors ligne
Perso je procède avec les contexte ainsi (Exemple simple sans controlle de présence/contenu des variables) :
public function init() { $contexts = array( 'update-mesure-audience' => 'json', 'delete-mesure-audience' => 'json', 'insert-mesure-audience' => 'json', ); $this->_helper->contextSwitch->addActionContexts($contexts)->initContext(); if(!$this->_helper->contextSwitch->hasActionContext($this->_request->getActionName(),'json')) { //Action à exectuer hors contexte json } } public function insertMesureAudienceAction() { if($this->_request->isPost()) { $table = new factory_listeMesuresAudience(); $mesure_audience = $table->createRow(); $mesure_audience->id_etude = $this->_getParam('id_etude'); $mesure_audience->intitule = $this->_getParam('intitule'); $mesure_audience->fk_id_societe = $this->_getParam('id_societe'); $id = $mesure_audience->save(); if($id) { $this->view->message = $this->view->_('succes ajout'); $this->view->id = $id; } else { $this->view->message = $this->view->_('echec ajout'); } } }
Le Js qui va avec ...
var result = new Ajax.Request ( base_url+'/administration/insert-mesure-audience/?format=json', { method:'post' , parameters:{ 'id_societe' : id_societe, 'intitule' : libelle} , onSuccess: function(response) { var responseObject = eval('(' + response.responseText + ')'); message(responseObject.message); var id= responseObject.id; //Suite ... } } );
Par contre je ne trouve pas le moyen de ne pas avoir à faire "var responseObject = eval('(' + response.responseText + ')');" sur le retour js pour pouvoir choper mes variables.
Quelqu'un saurait comment faire pour récuperer mes variables en faisant directement "response.id", "response.message" .. etc?
Dernière modification par sebondus (29-10-2008 17:22:29)
Hors ligne
personne?
Hors ligne
Bonjour sebondus,
Pourquoi ne pa sutiliser le helper Json ?
$this->_helper->json(?); // ? à encoder
Ce helper désactibe automatquement la vue, le layout en envoi le bon header, tu n'as plus grand chose à écrire.
Hors ligne
Tu es obligé de faire un eval en javascript
Le protocole HTTP ne sait pas ce que c'est un objet Javascript, tu fois faire un eval pour interprété ta chaine (objet javascript sérialisé) en objet javascript.
Perso, j'utilise Jquery pour faire mes requête ajax, et la fonction fait elle même appel à 'eval'.
De plus, j'utilise AjaxContext, et pas ContextSwitch. (voir la doc pour la différence)
En plus de plus, pour le contexte prédéfini 'json', la vue n'est pas nécessaire. Il désactive automatiquement le layout et envoi les variables de vue sérialisée (sauf si on ne le veut pas, voir la doc et la fonction setAutoJsonSerialization). Donc, le helper n'est pas nécessaire.
Hors ligne
alien7 a écrit:
Bonjour sebondus,
Pourquoi ne pa sutiliser le helper Json ?Code:
$this->_helper->json(?); // ? à encoderCe helper désactibe automatquement la vue, le layout en envoi le bon header, tu n'as plus grand chose à écrire.
Voila the réponse on dirait ^^ Merci !
Hors ligne
j'utilse ça
success:function(form, action){ var res = Ext.util.JSON.decode(action.response.responseText); ...
mais avec EXtJS pour ce qui est des grid combo form et autre composant il suffit de lui donner l'url et de décrire la structure de la réponse. il fait le reste tout seul.
Je ne fais donc ça que dans de très rares cas.
A+JYT
Hors ligne
Salut,
la page de json recense des classes dans pas mal de langages pour parser du json
http://www.json.org/
Perso, je n'utilise pas eval en js et je ne le faisais pas non plus en actionscript1 (flash), ça peut créer des erreurs ou des trous de sécu...
a+
Hors ligne