AJAX i JSON w Zend Framework
Zacząłem niedawno nowy projekt. Kolejny oparty o Zend Framework, a tym razem w znacznym stopniu wykorzystujący tzw. AJAX. Jednak zamiast zwracać XML wolę dane dostawać jako JSON. Jak to robię, wykorzystując dobrodziejstwa ZF? Pokażę na przykładzie akcji logowania.
Akcja logowania nie generuje u mnie żadnych formularzy ani tekstu. Służy tylko do wywołania przez zapytanie asynchroniczne i zwrócenia danych jako JSON.
Oto kod akcji:
class AccountController extends Zend_Controller_Action { function signinAction() { if($this->view->checkLogin())die(); $this->_helper->layout->setLayout('json'); $this->view->json = array('error'=>0, 'signin'=>false, 'message'=>''); if($this->_request->isPost()) { $f = new Zend_Filter_StripTags(); $login = $f->filter($this->_request->getPost('login','')); $password = $f->filter($this->_request->getPost('password','')); if(!empty($login)) { $authAdapter = new Zend_Auth_Adapter_DbTable(Zend_Db_Table::getDefaultAdapter(), 'users', 'email', 'passwd', 'MD5(?) AND is_deleted = 0'); $authAdapter->setIdentity($login); $authAdapter->setCredential($password); $auth = Zend_Auth::getInstance(); $result = $auth->authenticate($authAdapter); if($result->isValid()) { $data = $authAdapter->getResultRowObject(array('id_user', 'email', 'name', 'user_role')); $auth->getStorage()->write($data); $this->view->json['signin']=true; } } } if(!$this->view->json['signin']) $this->view->json['message']='Podane e-mail i hasło nie pasują do siebie.'; } }
Po kolei
Cała magia zaczyna się od
$this->_helper->layout->setLayout('json'); $this->view->json = array('error'=>0, 'signin'=>false, 'message'=>'');
czyli wybrania layoutu dla tej akcji i zainicjowania tablicy json w obiekcie view. Dalej odbywa się logowanie za pomocą modułu Zend_Auth (o tym może przy innej okazji) i odpowiednie wypełnianie tablicy json.
A po co był ten wybór layoutu? To nowość w wersji 1.5 frameworka. W pliku bootstrap (zazwyczaj index.php) należy go zainicjować dodając linijkę:
Zend_Layout::startMvc(array('layoutPath'=>ROOT_DIR.'/application/views/layouts/'));
Domyślny layout należy umieścić w pliku /application/views/layouts/layout.phtml – będzie on wczytywany dopóki go dla danej akcji nie wyłączymy lub nie zmienimy. To drugie zrobiłem właśnie w akcji logowania. A w pliku /application/views/layouts/json.phtml wrzuciłem tylko:
json(isset($this->json)?$this->json:array())?>
i wtedy cała odpowiedź akcji to przerobiona tablica json za pomocą zendowego helpera json(). Reszta to już kwestia JS i odpowiedniego odczytania zwróconego obiektu. Korzystam z mootools i tamtejszej metody Json.evaluate(); pobieranie danych za pomocą Json.Remote generowało błędy.
/* * url - adres akcji logowania - w przykładzie /account/signin/ * params - informacje logowania */ new Ajax(url, {'data':params, 'method': 'post', 'onComplete': function(t){ var data = Json.evaluate(t); if(!data) alert('Wystąpił błąd podczas logowania!'); if(data.error) alert('Wystąpił błąd podczas logowania!'); if(data.signin) alert('Zalogowany!'); else alert(data.message); }
Podsumowanie
Oczywiście logowanie to tylko przykład tworzenia wyniku JSON. Najważniejsze elementy to:
- zainicjowanie Zend_Layout;
- utworzenie tablicy json (tylko ten krok należy wykonać w każdej akcji, pozostałe wykonają się automagicznie);
- zdefiniowanie layoutu jsonowego;
- przekształcenie tablicy do JSON w layoucie;
- skrypt akcji w views może zostać pusty.
Uhm i właśnie dlatego nie piszę w php. Toż to przecież java…
$f->filter($this->_request->getPost(‘login’,’‘));
Nie, dziękuję :).
Cała magia zaczyna się tu:
if($this->view->checkLogin())die();
Jak jest zalogowany, to nie będzie tego przez AJAX wywoływał. A jak wywołuje, to znaczy, że coś przekręcił. A jak przekręcił, to jego problem.
die() jest raczej do skryptów. Dla www powinieneś zwracać kod błędu http.
Pingback: AJAX i JSON w Zend Framework 2