PHPGangsta - Der praktische PHP Blog

PHP Blog von PHPGangsta


Nicht-HTML-Responses mit dem Zend Framework

with 5 comments

Wenn man dynamische Bilder oder RSS-Feeds oder einen AJAX/JSON-Service oder ein Excel-Export mithilfe des Zend Frameworks erstellen will, mußt man 2-3 wichtige Dinge beachten. Der Code soll dann in einem Rss-/Graph-/Ajax-/Export-Controller stehen.

Ein Problem bekommt man, wenn man ein Layout benutzt (Zend_Layout). Denn dann wird dieses Layout immer ausgegeben. Im hier betrachteten Fall wäre das aber sehr schädlich, denn dadurch würden wir unser Bild/RSS-Feed/AJAX/Excel-Response zerstören.

Unschön kann man das wie folgt lösen:

public function rssAction()
{
	// calculate rss data and echo it (with correct headers)

	exit;
}

Richtig und deutlich schöner ist das Abschalten des Layout in der Action, wie folgt:

public function rssAction()
{
	// disable layout
	$this->_helper->layout()->disableLayout();
	
	// disable view rendering
	$this->_helper->viewRenderer->setNoRender();
	
	// calculate rss data and echo it (with correct headers)
}

Wir schalten auch gleich noch den ViewRenderer mit aus, damit auch nicht versucht wird, ein Viewscript zu rendern (das es wahrscheinlich garnicht gibt).

Dieses RSS-Beispiel funktioniert natürlich genauso für die anderen Beispiele, wo kein klassischer HTML-Quelltext zurückgegeben werden soll, sondern eine Antwort in einem anderen Format gefordert ist.

Damit kann man dann seine dynmisch erstellten Bilder (z.B. mittels pChart, jpgraph oder direkt die GD-Funktionen/image* in php), RSS-Feeds (Zend_Feed), Ajax-Services (Zend_Json) usw. realisieren.

Hier noch schnell ein Beispiel eines Excel-Exports aus einer Datenbank, mit Hilfe der Spreadsheet-Klasse aus dem PEAR-Framework (vereinfacht auf das Wesentliche):

class ExportController extends Zend_Controller_Action
{	
	public function excel() {
		// disable layout
		$this->_helper->layout()->disableLayout();
		
		// disable view rendering
		$this->_helper->viewRenderer->setNoRender();

		
		// get some data from database here
		
		       
		// create empty file
		//include 'Spreadsheet/Excel/Writer.php';
		$excel = new Spreadsheet_Excel_Writer();
		// add worksheet
		$sheet =& $excel->addWorksheet('Daily Export');

		$sheet->setColumn(0,0,20);
		$sheet->setColumn(1,1,15);
		$sheet->setColumn(2,2,18);
		$sheet->setColumn(3,3,23);
		$sheet->setColumn(4,4,35);
		$sheet->setColumn(5,5,15);

		$format_bold =& $excel->addFormat();
		$format_bold->setBold();

		$format_headline =& $excel->addFormat();
		$format_headline->setBold();
		$format_headline->setSize(20);
		$format_headline->setAlign('center');

		// headline
		$sheet->write(0, 0, 'Results: '.date('d.m.Y H:i'), $format_headline);
		$sheet->mergeCells(0,0,0,5);

		// add data to worksheet
		$rowCount=2;

		foreach ($data as $groupName=>$serverData) {
			$sheet->write($rowCount, 0, $groupName, $format_bold);
			$rowCount++;

			foreach ($serverData as $row) {
				$colcount = 0;
				foreach ($row as $key => $value) {
					$sheet->write($rowCount, $colcount, $value);
					$colcount++;
				}
				$rowCount++;
			}
			$rowCount++;
		}
		// send client headers
		$excel->send('daily_export_'.date("Ymd-His").'.xls');
	}		
}

Dies hier ist alter Code, mittlerweile nutzen wir PHPExcel.

Written by Michael Kliewe

Juli 2nd, 2009 at 2:52 pm

Posted in PHP

Tagged with , , , , , ,

5 Responses to 'Nicht-HTML-Responses mit dem Zend Framework'

Subscribe to comments with RSS or TrackBack to 'Nicht-HTML-Responses mit dem Zend Framework'.

  1. Die Beschreibung humpelt etwas: Zend_View (und Zend_Layout) sind beide nicht pauschal auf HTML festgelegt. Es reicht also völlig aus, wenn das View-Skript eben kein HTML enthält, sondern etwas Anderes, zB XML (RSS). Und anstelle das Layout gleich zu deaktivieren, kann man es auch (hier) ein XML-Layout einstellen. So kann man Nicht-HTML auf alt-hergebrachten Weg rendern lassen, was vorallen die Übersicht steigert. Content-Type muss man allerdings trotzdem setzen 😉

    Dein erstes Beispiel ist nebenbei nicht nur „unschön“, sondern kann auch negative sideeffects haben: Was ist mit den Plugins mit postDispatch()-Hooks?

    KingCrunch

    6 Jul 09 at 17:41

  2. Deshalb schrieb ich ja „unschön“. Es ist die erste Idee, die man so hat, wenn man neu mit dem ZF arbeitet, und es funktioniert ja auch in 99% aller Fälle.

    Man könnte sicherlich noch weitere Beispiele finden, warum es „unschön“ ist, postDispatch-Hooks sind ein weiteres Beispiel.

    Michael Kliewe

    6 Jul 09 at 18:59

  3. Wenn man JSON als Antwort aus dem Controller heraus senden will, kann man das auch noch einfacher machen, ohne selbst den ViewRenderer oder das Layout auszuschalten, und zwar mit folgendem:

    $this->getHelper(‚Json‘)->sendJson($foo);

    Dabei wird auch gleichzeitig alles ins JSON-Format konvertiert 🙂

    Dennis Becker

    10 Jul 09 at 10:01

  4. Du hast Recht, denn in dem Helper wird das Layout disabled. Es ist also unnötig, dies in der Action zu tun.
    Auch hier nachzulesen:
    http://framework.zend.com/manual/en/zend.controller.actionhelpers.html#zend.controller.actionhelpers.json

    Aber irgendwer muss das Layout disablen, soweit sind wir uns einig 😉

    Michael Kliewe

    10 Jul 09 at 10:54

  5. @Kingdings
    Was ist dann mit Plugins mit PostDispatch die nichts ausgeben aber etwas ausführen sollen, un soforn hätten auch andere lösungen nachteile. ich finde diese am schönsten von dem anderem „kram“ den ich bisher gesehen habe. Das Layout lässt sich auch ohne den helper disablen, ($this->view->layout()->disableLayout();)

    Natürlich kann man auch ein XML Layout basteln aber hier übernimmt ja eine andere klasse (Spreadsheet_dingens) die komplette generierung.

    Seo Consultant

    23 Jul 09 at 17:09

Leave a Reply

You can add images to your comment by clicking here.