2009-09-30 2 views
7

Avvierò un progetto utilizzando un'implementazione MVC di Zend Framework.MVC: come ajax?

Come lavoro con ajax? Voglio dire, dovrei mettere tutto il codice Ajax nel controller? O in vista?

Ad esempio, desidero ottenere post dall'autore "ivan" da mostrare su una pagina.

Generalmente, creo un collegamento a "/ posts/author/ivan" o smth come esso, crea una nuova azione come "byAuthorAction()" nel controller Post (o forse nel controller Users, ovunque), visualizza per esso (e tutto il codice che ottiene i post dal modello va lì) e crea una nuova rotta.

Come aggiungere funzionalità per ottenere post di qualsiasi utente in json, formati xml per ajax e forse API, mantenendo il principio di DRY e progettando la struttura del codice il più intelligente possibile?

-

Grazie per le risposte! Sarò molto contento di vedere commenti sulla progettazione di MVC in situazioni come la mia. Ho una certa esperienza in principi di base MVC ma non in casi più complicati. Forse alcuni link utili?

risposta

13

si dovrebbe davvero leggere il capitolo del manuale su ContextSwitch Azione Helper. Ma ecco un breve riassunto:

  • vostri script vista (azione-name.phtml) vengono utilizzati per l'uscita regolare HTML
  • è possibile inizializzare un cambio di contesto per alcune azioni nel controller in modo thay può produrre per esempio Il contesto XML - xml è supportato per impostazione predefinita e si inserisce lo script di visualizzazione per il contesto xml in (action-name.xml.phtml); il contesto xml disabilita anche il rendering del layout
  • json è anche supportato dall'interruttore di contesto integrato e l'opzione predefinita è di disabilitare sia il layout che la vista e di generare tutte le variabili assegnate alla vista dall'azione del controller nel formato JSON , questa opzione può essere attivata usando il metodo setAutoJsonSerialization (false) dell'interruttore di contesto; ma se lo si cambia, è necessario creare uno script di visualizzazione action-name.json.phtml ed emette le variabili in formato JSON a mano

Per passare da uno di questi due contesti devi aggiungere un parametro di formato al tuo URL, ad es./post/autore/ivan/format/json o/posts/author/ivan/format/xml. Se non si specifica il formato, l'applicazione emetterà semplicemente html.

La versione speciale dell'interruttore di contesto è AjaxContext e anche questa deve essere configurata manualmente. Non usa il parametro 'format' per identificare il formato che dovrebbe usare per l'output ma esamina l'intestazione inviata nella richiesta e cerca l'intestazione 'X-Requested-With: XmlHttpRequest' e se è presente viene esaminato l'AjaxContext. Utilizzando l'helper azione AjaxContext è possibile specificare quale contesto deve essere utilizzato per azioni specifiche se la richiesta viene attivata utilizzando AJAX.

8

È possibile utilizzare le stesse azioni per restituire XML, JSON o qualsiasi altra cosa, rilevando richieste ajax e quindi in grado di differenziare le richieste Ajax da quelle normali. Per esempio:

public function fooAction() 
{ 
    if($this->getRequest->isXmlHttpRequest()) { 
     echo json_encode($someData); 
    } else { 
     echo 'This is the normal output'; 
    } 
} 
+0

come scegliere tra xml e json? dovrei formattare url come/posts/author/ivan per html, /posts/author/ivan.xml, /posts/author/ivan.json, /posts/author/ivan.rss ecc per i formati? –

+0

No, l'URL sarebbe lo stesso. È possibile utilizzare json_encode() per stampare il contenuto in formato JSON. http://ar2.php.net/json_encode –

+0

json è più leggero e più facile da utilizzare con IMO. Potresti creare una vista JSON o potresti echo json_encode() nell'array di dati senza usare una vista, probabilmente dovresti disattivare il rendering automatico della vista. – karim79

2

tuo View può essere qualcosa di diverso da HTML, e sia la pipeline in grado di reagire alla richiesta di essere un posto ajax, o il controller in grado di reagire. In ogni caso, dovrebbe essere semplice come restituire una vista diversa.

1

Dai un'occhiata all'Action-Action di AjaxContext (o a quello di ContextSwitch, che estende) e ti consente di utilizzare esattamente lo stesso codice di controller, passando a uno script di visualizzazione separato (foo.json. phtml, o foo.ajax.phtml ecc. - prelevati automaticamente da un parametro? format), o fare uso del JSON Action-Helper che restituirà un oggetto che comprende tutte le variabili che assegni alla vista - quindi non devi farti eco dal tuo controller (che rovinerà i test unitari, se li avessi).

+0

oh, certo. come posso non averlo visto? –

0

la mia sintassi potrebbe essere più anziani, ma questo uno schizzo della mia azione REST dal mio controller Indice:

/** 
* REST Action for this application. 
* 
* @return void 
*/ 
public function restAction() 
{ 
    $this->_helper->viewRenderer->setNoRender(true); 

    $parameters = (func_num_args() > 0) ? array($key => func_get_arg(0)) : $this->getRequest()->getParams(); 

    $key = 'restCommand'; 
    if(!array_key_exists($key, $parameters)) throw new Exception('Request for “' . $key . '” not found.'); 
    $restCommand = $parameters[$key]; 

    $xmlString = IndexModel::getEmptyXmlSet($restCommand); 
    $xslFile = IndexModel::getModelFilePath('index'); 

    //Handle OPML-driven REST commands: 
    if(stripos($restCommand, 'opml-') === 0) 
    { 
     $opmlCall = explode('-', $restCommand); 
     if(count($opmlCall) != 3) 
     { 
      $xmlString = Songhay_SimpleXml::getXmlMessage('OPML Call Not Recognized', array('The number of parameters are incorrect.')); 
     } 
     else 
     { 
      $opmlSet = $opmlCall[1]; 
      $opmlId = $opmlCall[2]; 
      $xmlString = IndexModel::getRssFragmentWithOpml($opmlSet, $opmlId); 
     } 
    } 

    //Handle general REST commands: 
    switch($restCommand) 
    { 
     case 'deeplink': 
      $key = 'id'; 
      if(!array_key_exists($key, $parameters)) throw new Exception('Request for “' . $key . '” not found.'); 
      $url = $parameters[$key]; 
      $xmlString = IndexModel::getRssFragment($url); 
      $xmlString = Songhay_SimpleXml::loadXslString($restCommand, $xmlString, $xslFile); 
      break; 
     case 'index': 
      $opmlFile = IndexModel::getModelFilePath('index', '.xml'); 
      $xmlString = Songhay_SimpleXml::loadXmlAndStripNamespaces($opmlFile); 
      $xmlString = Songhay_SimpleXml::loadXslString($restCommand, $xmlString, $xslFile); 
      break; 
     default: 
      $xmlString = Songhay_SimpleXml::loadXslString($restCommand, $xmlString, $xslFile); 
    } 

    $response = $this->getResponse(); 
    $response->setHeader('Content-Type', 'text/xml'); 
    $response->setBody($xmlString); 

    return; 
} 
0

Quando utilizzo ajax con codeigniter, viene emesso direttamente dal controller.

Uso anche un controller separato per semplici richieste ajax come segnalazioni, preferiti, ecc. Per richieste ajax come login, contatti, ecc. Aggiungerei la logica al normale percorso (ad esempio domain.com/contact) gestisco un richiesta di ajax. Eseguo quindi json e uccido l'esecuzione dello script.