<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:series="http://unfoldingneurons.com/"
	>

<channel>
	<title>sorgalla.com &#187; HTTP</title>
	<atom:link href="http://sorgalla.com/tag/http/feed/" rel="self" type="application/rss+xml" />
	<link>http://sorgalla.com</link>
	<description>PHP, Zend Framework, Datenbanken und was sonst noch so anfällt.</description>
	<lastBuildDate>Tue, 05 Jul 2011 07:20:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Ajax-Applikationen mit dem Zend Framework</title>
		<link>http://sorgalla.com/2009/12/30/ajax-applikationen-mit-dem-zend-framework/</link>
		<comments>http://sorgalla.com/2009/12/30/ajax-applikationen-mit-dem-zend-framework/#comments</comments>
		<pubDate>Wed, 30 Dec 2009 21:31:58 +0000</pubDate>
		<dc:creator>jan</dc:creator>
				<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://sorgalla.com/?p=281</guid>
		<description><![CDATA[Ajax wird heute in fast jeder modernen Webanwendung genutzt, bietet doch jedes gute Javascript-Framework mittlerweile einfache Möglichkeiten XHR-Anfragen abzusetzen. In diesem Artikel soll es aber nicht um die Client-Seite gehen, sondern darum, wie man auf der Server-Seite XHR-Anfragen erkennt und entsprechend darauf reagiert (Der Einfachheit halber rede ich hier nur von Ajax, weite Teile lassen [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://de.wikipedia.org/wiki/Ajax_(Programmierung)">Ajax</a> wird heute in fast jeder modernen Webanwendung genutzt, bietet doch <a href="http://jquery.com">jedes</a> <a href="http://www.dojotoolkit.org">gute</a> Javascript-Framework mittlerweile einfache Möglichkeiten <a href="http://de.wikipedia.org/wiki/XMLHttpRequest">XHR</a>-Anfragen abzusetzen. In diesem Artikel soll es aber nicht um die Client-Seite gehen, sondern darum, wie man auf der Server-Seite XHR-Anfragen erkennt und entsprechend darauf reagiert (Der Einfachheit halber rede ich hier nur von Ajax, weite Teile lassen sich aber natürlich auch auf den Bereich <a href="http://de.wikipedia.org/wiki/Webservice">Webservices</a> übertragen).<span id="more-281"></span></p>
<h3>HTTP richtig nutzen</h3>
<p>Clients können z. B. über <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html">Request-Header</a> dem Server mitteilen welches Rückgabe-Format sie erwarten oder bereits an korrekt gesetzten <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">Status-Codes</a> erkennen, ob die Anfrage fehlgeschlagen ist oder nicht. Diese Art der Kommunikation setzt voraus, dass der Server korrekt antwortet. Deshalb sollte man eingehende Request-Header überprüfen und verarbeiten und entsprechende Response-Header setzen.</p>
<table class="summary">
<caption>Allgemeine HTTP Request-Header</caption>
<tbody>
<tr>
<th>Content-Type</th>
<td>Der Content-Type der Daten die an die Applikation geschickt werden, z.B. <code>application/json</code></td>
</tr>
<tr>
<th>Accept</th>
<td>Der Content-Type den der Client in der Antwort erwartet, z. B. <code>application/json</code></td>
</tr>
<tr>
<th>Range</th>
<td>Anzahl Bytes oder Einheiten (items) die in der Antwort enthalten sein sollen. Die W3C-Spezifikation führt nur Byte-Ranges explizit aus. <code>dojox.data.JsonRestStore</code> z. B. nutzt den Range-Header für das Paging in der Form <code>Range: items=0-24</code> (<a href="http://docs.dojocampus.org/dojox/data/JsonRestStore#paging">Siehe Dokumentation</a>).</td>
</tr>
</tbody>
</table>
<table class="summary">
<caption>Allgemeine HTTP Response-Header</caption>
<tbody>
<tr>
<th>Content-Type</th>
<td>Der Content-Type der Daten die an den Client zurückgeschickt werden, z.B. <code>application/json</code></td>
</tr>
<tr>
<th>Vary</th>
<td>Der Vary-Header gibt dem Client oder Caching-Proxies Hinweise welche Header für das Caching verwendet werden sollen. Eine Resource kann verschiedene Darstellungsformen, abhängig vom gesendet Accept-Header, zurückliefern (z. B. eine Anfrage auf die URI <code>/resource/id</code> mit <code>Accept: text/html</code> liefert eine normal HTML-Seite und <code>Accept: application/json</code> auf die gleich URI liefert die Daten als JSON). Dadurch kann die URI nicht als eindeutige ID für das Caching verwendet werden. Ein <code>Vary: Accept</code> hilft dann dem Client oder Proxy die Antwort korrekt cachen zu können. Mehr dazu: <a href="http://www.subbu.org/blog/2007/12/vary-header-for-restful-applications">Vary Header for RESTful Applications</a>.</td>
</tr>
<tr>
<th>Content-Range</th>
<td>Anzahl Bytes oder Einheiten (items) die zurückgegeben werden. Analog zum oben beschriebenen Range-Header kann man folgendes Format verwenden: <code>Content-Range: items 0-24/66</code>. Dabei wird der Start- und End-Offset (0-24) und die Gesamtanzahl der verfügbaren Einheiten angeben (66).</td>
</tr>
</tbody>
</table>
<table class="summary">
<caption>Allgemeine HTTP Status-Codes</caption>
<tbody>
<tr>
<th>201 (Created)</th>
<td>Nach einem <a href="http://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol#HTTP-Request-Methoden">POST</a> der eine Resource erstellt hat.</td>
</tr>
<tr>
<th>204 (No Content)</th>
<td>Nach einem <a href="http://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol#HTTP-Request-Methoden">DELETE</a> der eine Resource gelöscht hat.</td>
</tr>
<tr>
<th>400 (Bad Request)</th>
<td>Validierungen sind fehlgeschlagen.</td>
</tr>
<tr>
<th>500 (Internal Server Error)</th>
<td>Applikations-Fehler, z. B. wenn eine Exception geworfen wurde.</td>
</tr>
</tbody>
</table>
<p>Ben Ramsey hat in seinem Blog eine <a href="http://benramsey.com/archives/http-status-100-continue/">kleine lesenswerte Reihe</a> zu HTTP Status-Codes.</p>
<h3>Request-Header verarbeiten mit einem Frontcontroller-Plugin</h3>
<p>Wir erstellen uns ein <a href="http://framework.zend.com/manual/de/zend.controller.plugins.html">Frontcontroller-Plugin</a>, welches die eingehenden Header inspiziert und manipulieren das Request-Objekt entsprechend. So können wir in unseren Action-Controllern auf gewohntem Wege über das Request-Objekt auf die Parameter zugreifen.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #009933; font-style: italic;">/**
 * @see Zend_Controller_Plugin_Abstract
 */</span>
<span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">'Zend/Controller/Plugin/Abstract.php'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * @see Zend_Controller_Request_Http
 */</span>
<span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">'Zend/Controller/Request/Http.php'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * @package    App_Controller
 * @subpackage App_Controller_Plugin
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> App_Controller_Plugin_HttpHandler <span style="color: #000000; font-weight: bold;">extends</span> Zend_Controller_Plugin_Abstract
<span style="color: #009900;">&#123;</span>
    <span style="color: #009933; font-style: italic;">/**
     * Called before Zend_Controller_Front enters its dispatch loop.
     *
     * @param  Zend_Controller_Request_Abstract $request
     * @return void
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> dispatchLoopStartup<span style="color: #009900;">&#40;</span>Zend_Controller_Request_Abstract <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$request</span> instanceof Zend_Controller_Request_Http<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #000088;">$vary</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Process Accept-Header (the format parameter will later be used by the ContextSwitch helper)</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span> <span style="color: #339933;">!==</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$accept</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getHeader</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Accept'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">strstr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$accept</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'application/xml'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">!</span><span style="color: #990000;">strstr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$accept</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'html'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setParam</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'format'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'xml'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000088;">$vary</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Accept'</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">elseif</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">strstr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$accept</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'application/json'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setParam</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'format'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'json'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000088;">$vary</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Accept'</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Process non-standard Content-Types</span>
        <span style="color: #000088;">$rawBody</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRawBody</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$rawBody</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span> <span style="color: #339933;">!==</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$contentType</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getHeader</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Content-Type'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">strstr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$contentType</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'application/xml'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span>
                    <span style="color: #990000;">strstr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$contentType</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'text/xml'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    <span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">'Zend/Config/Xml.php'</span><span style="color: #339933;">;</span>
                    <span style="color: #000088;">$config</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Config_Xml<span style="color: #009900;">&#40;</span><span style="color: #000088;">$rawBody</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                    <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setPost</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">toArray</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">elseif</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">strstr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$contentType</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'application/json'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    <span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">'Zend/Json.php'</span><span style="color: #339933;">;</span>
                    <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setPost</span><span style="color: #009900;">&#40;</span>Zend_Json<span style="color: #339933;">::</span><span style="color: #004000;">decode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$rawBody</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Process Range-Header</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span> <span style="color: #339933;">!==</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$range</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getHeader</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Range'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/items=(\d+)\-(\d+)/i'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$range</span><span style="color: #339933;">,</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setParam</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'range_start'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setParam</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'range_end'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000088;">$vary</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Range'</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Set Vary-Header</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$vary</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$response</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #666666; font-style: italic;">// Keep existing Vary headers</span>
            <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$response</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getHeaders</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$header</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">strtolower</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$header</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #0000ff;">'vary'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    <span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
&nbsp;
                <span style="color: #000088;">$vary</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$header</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'value'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
                <span style="color: #000088;">$response</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">clearHeader</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$header</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
&nbsp;
            <span style="color: #000088;">$response</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setHeader</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Vary'</span><span style="color: #339933;">,</span> <span style="color: #990000;">implode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">', '</span><span style="color: #339933;">,</span> <span style="color: #000088;">$vary</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h3>Ausgabe-Formate variieren mit dem ContextSwitch-Action-Helper</h3>
<p>Der standardmäßig im Zend Framework enthaltene <a href="http://framework.zend.com/manual/de/zend.controller.actionhelpers.html#zend.controller.actionhelpers.contextswitch">ContextSwitch-Action-Helper</a> bietet uns die Möglichkeit für einzelne Actions verschiedene Kontexte zu definieren.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">class</span> NewsController <span style="color: #000000; font-weight: bold;">extends</span> Zend_Controller_Action
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> init<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_helper<span style="color: #339933;">-&gt;</span><span style="color: #004000;">contextSwitch</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
            <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setAutoJsonSerialization</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>
            <span style="color: #339933;">-&gt;</span><span style="color: #004000;">addActionContext</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'list'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'json'</span><span style="color: #009900;">&#41;</span>
            <span style="color: #339933;">-&gt;</span><span style="color: #004000;">initContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * List news items
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> listAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_request<span style="color: #339933;">-&gt;</span><span style="color: #004000;">range_start</span> <span style="color: #339933;">||</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_request<span style="color: #339933;">-&gt;</span><span style="color: #004000;">range_end</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$start</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>int<span style="color: #009900;">&#41;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_request<span style="color: #339933;">-&gt;</span><span style="color: #004000;">range_start</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$end</span>   <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>int<span style="color: #009900;">&#41;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_request<span style="color: #339933;">-&gt;</span><span style="color: #004000;">range_end</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #000088;">$paginator</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$newsModel</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getItemsAsZendPaginatorObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #000088;">$count</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$paginator</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTotalItemCount</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$limit</span> <span style="color: #339933;">=</span> <span style="color: #339933;">!</span><span style="color: #000088;">$end</span> ? <span style="color: #000088;">$count</span> <span style="color: #339933;">:</span> <span style="color: #000088;">$end</span> <span style="color: #339933;">-</span> <span style="color: #000088;">$start</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$end</span>   <span style="color: #339933;">=</span> <span style="color: #339933;">!</span><span style="color: #000088;">$end</span> ? <span style="color: #000088;">$count</span> <span style="color: #339933;">:</span> <span style="color: #000088;">$end</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">items</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$paginator</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAdapter</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getItems</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$start</span><span style="color: #339933;">,</span> <span style="color: #000088;">$limit</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #666666; font-style: italic;">// Set Content-Range-Header</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_response
                <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setHttpResponseCode</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">206</span><span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">// Partial content header</span>
                <span style="color: #339933;">-&gt;</span><span style="color: #004000;">setHeader</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Content-Range'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'items '</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$start</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'-'</span><span style="color: #339933;">.</span> <span style="color: #000088;">$end</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$count</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">items</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$newsModel</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAllItems</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Wir haben in diesem Controller also für die Aktion <code>listAction</code> den zusätzlichen Kontext <code>json</code> definiert und präparieren sie so für die Verwendung per Ajax.</p>
<p>Ein &#8220;context switch&#8221; wird durch den <code>format</code>-Request-Parameter augelöst. Der Parameter wird hier durch unser Plugin gesetzt, kann aber natürlich auch über die URL definiert werden (z. B. <code>/news/list/format/json</code>).  Ist der <code>format</code>-Parameter nun also auf <code>json</code> gesetzt, wird automatisch der Kontext-Name an das View-Skript angehängt. Es wird statt <code>list.phtml</code> das View-Skript <code>list.<strong>json</strong>.phtml</code> gerendert. Außerdem wird der entsprechende Content-Type-Header <code>application/json</code> gesetzt und das Rendern der Layouts deaktiviert.</p>
<p>Ein kleiner Hinweis zum JSON-Kontext: Standardmäßig wird kein View-Skript gerendert sondern es werden einfach alle dem View-Objekt zugewiesenen Variablen serialisiert und direkt ausgegeben. Dieses Verhalten haben wir oben mit <code>setAutoJsonSerialization(false)</code> deaktiviert um eine bessere Kontrolle über die Ausgabe per View-Skript zu haben.</p>
<p>Das View-Skript <code>list.json.phtml</code> kann z. B. so aussehen:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">json</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">items</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">toArray</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Neben dem ContextSwitch-Helper gibt auch noch den AjaxContext-Helper. Der einzige Unterschied ist, dass dieser nur bei einer Anfrage per Ajax ausgeführt wird (d. h. wenn der Header <code>X-Requested-With: XMLHttpRequest</code> gesetzt ist).</p>
<h3>RESTvolle Controller</h3>
<p>Ein weitere Möglichkeit per Ajax mit der Applikation zu kommunizieren ist <a href="http://de.wikipedia.org/wiki/Representational_State_Transfer">REST</a>. Das Zend Framework bietet dafür <a href="http://framework.zend.com/manual/de/zend.controller.router.html#zend.controller.router.routes.rest">Zend_Rest_Route</a>.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$router</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addRoute</span><span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">'rest'</span><span style="color: #339933;">,</span>
    <span style="color: #000000; font-weight: bold;">new</span> Zend_Rest_Route<span style="color: #009900;">&#40;</span><span style="color: #000088;">$frontcontroller</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
        <span style="color: #0000ff;">'default'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
            <span style="color: #0000ff;">'news'</span><span style="color: #339933;">,</span>
        <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Damit haben wir den <code>NewsController</code> im <code>default</code>-Modul &#8220;RESTvoll&#8221; gemacht. Der Controller erweitert dann <a href="http://framework.zend.com/manual/de/zend.controller.router.html#zend.rest.controller">Zend_Rest_Controller</a> und muss dabei die Methoden indexAction(), getAction(), postAction(), putAction() und deleteAction() implementieren.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">class</span> NewsController <span style="color: #000000; font-weight: bold;">extends</span> Zend_Rest_Controller
<span style="color: #009900;">&#123;</span>
    <span style="color: #009933; font-style: italic;">/**
     * The index action handles index/list requests; it should respond with a
     * list of the requested resources.
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> indexAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * The get action handles GET requests and receives an 'id' parameter; it
     * should respond with the server resource state of the resource identified
     * by the 'id' value.
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * The post action handles POST requests; it should accept and digest a
     * POSTed resource representation and persist the resource state.
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> postAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * The put action handles PUT requests and receives an 'id' parameter; it
     * should update the server resource state of the resource identified by
     * the 'id' value.
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> putAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * The delete action handles DELETE requests and receives an 'id'
     * parameter; it should update the server resource state of the resource
     * identified by the 'id' value.
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> deleteAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Der Vorteil hierbei ist, dass wir ein vorhersagbares API bereitstellen. Dojo zum Beispiel bietet mit der Kombination <a href="http://docs.dojocampus.org/dojox/data/JsonRestStore">dojox.data.JsonRestStore</a> und <a href="http://docs.dojocampus.org/dojox/grid/DataGrid">dojox.grid.DataGrid</a> alles was man zur Implementierung von <a href="http://de.wikipedia.org/wiki/CRUD">CRUD</a>-Operationen braucht.</p>
<h3>Links zum Thema</h3>
<ul>
<li><a href="http://www.slideshare.net/weierophinney/architecting-ajax-applications-with-zend-framework">Architecting Ajax Applications with Zend Framework</a></li>
<li><a href="http://framework.zend.com/manual/de/zend.controller.actionhelpers.html#zend.controller.actionhelpers.contextswitch">ContextSwitch-Action-Helper</a></li>
<li><a href="http://framework.zend.com/manual/de/zend.controller.router.html#zend.controller.router.routes.rest">Zend_Rest_Route</a></li>
</ul>
<div class="tweetthis" style="text-align:left;"><p> <a target="_blank" class="tt" href="http://twitter.com/intent/tweet?text=Ajax-Applikationen+mit+dem+Zend+Framework+http%3A%2F%2Fsorgalla.com%2F%3Fp%3D281+%2Fby+%40jansor" title="Post to Twitter"><img class="nothumb" src="http://sorgalla.com/wp-content/plugins/tweet-this/icons/en/twitter/tt-twitter3.png" alt="Post to Twitter" /></a> <a target="_blank" class="tt" href="http://delicious.com/post?url=http://sorgalla.com/2009/12/30/ajax-applikationen-mit-dem-zend-framework/&amp;title=Ajax-Applikationen+mit+dem+Zend+Framework" title="Post to Delicious"><img class="nothumb" src="http://sorgalla.com/wp-content/plugins/tweet-this/icons/en/delicious/tt-delicious.png" alt="Post to Delicious" /></a> <a target="_blank" class="tt" href="http://digg.com/submit?url=http://sorgalla.com/2009/12/30/ajax-applikationen-mit-dem-zend-framework/&amp;title=Ajax-Applikationen+mit+dem+Zend+Framework" title="Post to Digg"><img class="nothumb" src="http://sorgalla.com/wp-content/plugins/tweet-this/icons/en/digg/tt-digg.png" alt="Post to Digg" /></a> <a target="_blank" class="tt" href="http://www.facebook.com/share.php?u=http://sorgalla.com/2009/12/30/ajax-applikationen-mit-dem-zend-framework/&amp;t=Ajax-Applikationen+mit+dem+Zend+Framework" title="Post to Facebook"><img class="nothumb" src="http://sorgalla.com/wp-content/plugins/tweet-this/icons/en/facebook/tt-facebook.png" alt="Post to Facebook" /></a> <a target="_blank" class="tt" href="http://reddit.com/submit?url=http://sorgalla.com/2009/12/30/ajax-applikationen-mit-dem-zend-framework/&amp;title=Ajax-Applikationen+mit+dem+Zend+Framework" title="Post to Reddit"><img class="nothumb" src="http://sorgalla.com/wp-content/plugins/tweet-this/icons/en/reddit/tt-reddit.png" alt="Post to Reddit" /></a></p></div>]]></content:encoded>
			<wfw:commentRss>http://sorgalla.com/2009/12/30/ajax-applikationen-mit-dem-zend-framework/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

