Ajax aplikacijos su Zend_Json_Server

Kas yra AJAX ir kam jis naudojamas – šiame straipsnyje plačiau neaptarinėsime. Verta tik paminėti, kad norėdami savo programas optimizuoti – turite turinį krauti asinchroniškai ir vengti pilno puslapio perkrovimo (aišku jei tai įmanoma). Nesenai aptikau vieną įdomų sprendimą Zend Framework naudojančioms sistemoms.
Taigi pirmiausia paskiriame kokį nors kontrolerį mūsų ajax užklausoms, pavyzdžiui /ajax bus apdorojamas kontroleriu AjaxController. Jame apsirašome metodą __call kuris perims kreipimąsi į neegzistuojančius metodus.

<?php
class AjaxController extends Zend_Controller_Action
{
    public function preDispatch() {
	    $this->_helper->viewRenderer->setNoRender(true);
	}
 
    public function __call($name,$arguments) {
    	$action = $this->getRequest()->getActionName();
    	// tikrinam ar prasideda klase Main_ jei ne - metame lauk
    	$parts = explode('_', $action);
    	if (empty($parts[1])) throw new Zend_Exception('undefined class',500);
    	if ((string)$parts[0] !== 'Main') throw new Zend_Exception('restricted access',500);
    	$autoloader = Zend_Loader_Autoloader::getInstance();
        $autoloader->registerNamespace('Main_');    	
    	$server = new Zend_Json_Server();
    	$server->setClass($action);
    	if ('GET' == $_SERVER['REQUEST_METHOD']) {		   
		    $server->setTarget(Zend_Registry::get('base_url').'ajax/'.$action)
		           ->setEnvelope(Zend_Json_Server_Smd::ENV_JSONRPC_2);
		    $smd = $server->getServiceMap();		    
		    header('Content-Type: application/json');
		    echo $smd;
		    return;
		}
    	$server->handle();
    }
}

Tuomet kataloge libraries susikuriame naują katalogą Main ir ten susikuriame naują failą Api.php su tokiu turiniu:

class Main_Api {
 
	public function getSmd($class) {
                 // Zend_Registry::get('base_url') gražina pilną svetainės adresą
		$client = new Zend_Http_Client(Zend_Registry::get('base_url').'ajax/'.$class, array(
    		'maxredirects' => 0,
    		'timeout'      => 30)
		);
		return $client->request(Zend_Http_Client::GET)->getRawBody();
	}
}

Iš PHP pusės viskas baigta, dabar keliaujame prie javascript

<script type="text/javascript" src="/js/jquery-1.5.1.min.js"></script>
<script type="text/javascript" src="/js/json2.js"></script>
<script type="text/javascript" src="/js/jquery.zend.js"></script>
<script type="text/javascript" src="/js/jquery.zend.jsonrpc.js"></script>
<script type="text/javascript" src="/js/init.js"></script>

Čia galite juos visus parsisiųsti
Faile init.js yra mano aprašytas „AutoLoader“ objektas kuris kai tik jums prireiks pakraus reikalingą PHP klasę iš bibliotekos Main. Taip pat galite dinamiškai pasikrauti ir javascript failus, bet kalba ne apie tai dabar :)
Naudojimas šios sistemos yra itin paprastas:

alert(AutoLoader.getClass('Main_Test').sum(1,2));

Su javascript kreipsitės tiesiai į PHP klasę esančią libraries/Main/Test.php

class Main_Test {	
	public function sum($a,$b) {
		return $a+$b;
	}
}

Ar gali būti paprasčiau ir patogiau? Man atrodo ne :) Dar vienas extra dalykas: jei kviesime objekto AutoLoader metodą getClass nurodę antrą parametrą true, tuomet užklausos bus siunčiamos asinchroniškai ir alert funkcija negaus jokio turinio. Tai yra todėl, kad pirmu atveju javascript laukia atsakymo iš serverio, o antru atveju – ne. Antras atvejis gali būti naudingas, kad išsaugome kokią informaciją serveryje ir mums nėra būtinybės gauti patvirtinimą apie sėkmingą transakciją ir panašiai.

Tikiuosi šis sprendimas privers bent nusišypsoti tuos, kurie nuolat naudoja AJAX savo sistemose, ir palengvins kasdienį darbą.

Žygimantas

Lead developer at Soundest. Zend Certified Engineer.

More Posts - Website

Žymos: , , ,

2 komentarai

  1. Atsisakyčiau tokio sprendimo. Per sudėtingas iš vienos pusės. Ir iš patirties galiu pasakyti, kad krauti visą framework vientik dėl kažkokios smulkios užklausos, neapsimoka.

  2. Tai niekas ir nekalba apie smulkias užklausas. Jei viskas ką turi užklausa padaryti yra tik mysql_query(), tai tada taip. Bet paprastai reikia tikrinti ar žmogus turi teisę atlikti veiksmą (ACL), ar tai atlieka tikrai pats žmogus (CSFR), jei veiksmui reikia, kad būtum prisijungęs va jau ir AUTH reikaliukus reikia sužiūrėt. Jau nekalbu apie DB abstrakcijas…

    Po straipsnio parašymo intensyviai naudoju pateiktą sprendimą, aišku kiek pamodifikuotą, tačiau esmė ta pati. Iki šiol viskas yra gerai, labai stipriai padeda tiek programuojant tiek ir išsaugant daugybę resursų didelėse sistemose.

Parašykite komentarą

El. pašto adresas nebus skelbiamas. Būtini laukeliai pažymėti *

Galite naudoti šias HTML žymas ir atributus: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>