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',''));
{
$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:
<?=
$this->
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.