PHPGangsta - Der praktische PHP Blog

PHP Blog von PHPGangsta


Zend_View Output Filter: Whitespaces aus HTML entfernen

with 22 comments

Zend Framework implementiert das Intercepting-Filter-Pattern, und dadurch ist es sehr einfach nach der Generierung des HTML-Codes (Postprocessor) einen Filter einzufügen, der die Ausgabe noch verändert. Natürlich gibt es auch Präprozessor-Filter, in denen man häufig die Authentifizierung prüft oder Eingabeparameter validiert.

Vorstellen könnte man sich beispielsweise einen Filter, der bestimmte Textblöcke ersetzt, um zum Beispiel aus „mailto:“-Links Bilder zu generieren oder sie anders zu schützen, beispielsweise mittels Javascript.

Man kann sich auch einen Filter vorstellen, der das HTML-Ergebnis durch den HTML-Purifier schickt, ihn also W3C-kompatibel macht. Dies sollte man jedoch vermeiden wenn eben möglich und seinen HTML-Code auch vorher bereits korrekt generieren.

In diesem Artikel möchte ich einen ganz einfachen Filter einrichten, der alle Tabs, Leerzeichen und Umbrüche entfernt, sodass der komplette HTML-Code in einer Zeile steht und keine unnötigen Whitespaces enthält. Man kann damit den Traffic um ca. 3-15% (nicht gzip’t) verringern, nur durch das Entfernen von Tabs und Leerzeichen! Es ersetzt natürlich nicht die Aktivierung von gzip, um „richtig“ Traffic zu sparen und die Webseite schneller zu machen.

Wir schreiben uns also einen einfachen Filter, der die Aufgabe erfüllt:

<?php
class App_View_Filter_Minify implements Zend_Filter_Interface
{
	public function filter($string)
	{
		return preg_replace(
			array('/>\s+/', '/\s+</', '/[\r\n]+/'),
			array('>', '<', ' '),
			$string
		);
	}
}

Die filter() Methode bekommt den Ausgabestring übergeben, wir filtern alle Whitespaces heraus und geben das Ergebnis zurück. Wir sind hier etwas vorsichtig und filtern nur direkt vor oder nach HTML-Tags.

Diesen Filter müssen wir nun noch einbauen, und das geht wie folgt in der Bootstrap.php, wo wir im View-Objekt den Filter aktivieren:

/**
 * Add Output filters to View
 *
 * @return void
 */
protected function _initViewFilter()
{
	$view = $this->getResource('view');
	$view->addFilterPath('App/View/Filter', 'App_View_Filter_')
		->addFilter('Minify');
}

Wir fügen dem View-Objekt also einen Pfad hinzu, wo wir den Filter abgelegt haben, und übergeben dann noch den Namen des Filters. Das Zend Framework wird dann nach der Abarbeitung der ControllerAction und dem Rendern des View-Scripts diesen Filter benutzen und die Ausgabe verändern.

Ergebnis ist dann eine einzelne Zeile HTML-Code ohne Whitespaces. Hier ein paar Ergebnisse dieses doch sehr einfachen Filters:

Größe vorher (KB)Größe nachher (KB)Ersparnis (%)
6,15,59,9
100,990,210,6
4,64,28,7
18,918,61,6

Written by Michael Kliewe

März 25th, 2010 at 9:19 am

22 Responses to 'Zend_View Output Filter: Whitespaces aus HTML entfernen'

Subscribe to comments with RSS or TrackBack to 'Zend_View Output Filter: Whitespaces aus HTML entfernen'.

  1. Ist das Entfernen direkt vor/nach Tags nicht auch relativ „gefährlich“?

    Wenn ich Ihn verhohnepiepeln will?

    würde dann ja (ohne die Formatierungen) in etwa so aussehen:

    WennichIhnverhohnepiepelnwill?

    Christian

    25 Mrz 10 at 10:04

  2. Ok, Tags sind hier erlaubt. *grmpf*

    Der „gefährliche“ Beispielsatz sollte eigentlich so aussehen:

    Wenn ich Ihn verhohnepiepeln will?

    Christian

    25 Mrz 10 at 10:05

  3. Hmpf! pre klappt wohl nicht. Noch ein Versuch? Vielleicht klappt’s ja mit HTML-Entities:

    <p>Wenn <strong>ich</strong> Ihn <em>verhohnepiepeln</em> will?</p>

    Christian

    25 Mrz 10 at 10:06

  4. hey,

    mir geistert zu dem Thema gerade eine Frage durch den Kopf… Ich kann es mir zwar fast nicht vorstellen, aber was meint ihr: besteht die Möglichkeit, dass die Suchmaschinen evt. auch die Whitspaces als Kriterium für die Struktur des Quellcodes heranziehen? An sich gehört zu einem „sauberen“ Quellcode auch eine „ordentliche“ Formatierung.
    Wichtigstes Gegenargument ist sicher die Komprimierung des Codes und damit der schneller Download der Daten.

    Vielleicht kann ja jemand anhand eine Quelle diesen wahrscheinlich unberechtigten Zweifel widerlegen…

    Grüße Christian

    Christian

    25 Mrz 10 at 10:11

  5. @Christian: Danke für den Tipp! Es gibt ja anscheinend doch Leute die meine Texte lesen UND verstehen 😉 Da war mein einfaches Beispiel doch zu einfach. In meinen Tests hatte ich einen solchen Fall nicht.

    Hier die verbesserte Version, schau bitte drüber, und wenn es korrekt ist verbessere ich es oben:

    return preg_replace(
    array(‚/>\s{2,}/‘, ‚/\s{2,}</‘, ‚/[\r\n]+/‘),
    array(‚> ‚, ‚ <‚, ‚ ‚),
    $string
    );

    Michael Kliewe

    25 Mrz 10 at 11:06

  6. Wenn da jetzt aber kein Text ist, sondern zwei Tags hintereinander stehen, nur mit vielen Leerzeichen, ist zwischen den Tags wieder ein Leerzeichen, was wir ja eigentlich nciht wollen.

    Markus

    25 Mrz 10 at 12:09

  7. Wiso heisst denn der Filter anders als im Bootstrap?

    Kevin

    25 Mrz 10 at 12:20

  8. Doch, das wollen wir, zum Beispiel bei diesem Beispiel soll das Leerzeichen ja stehen bleiben:

    <p>Wenn <strong>ich</strong> <i>Ihn</i> <em>verhohnepiepeln</em> will?</p>

    Michael Kliewe

    25 Mrz 10 at 12:20

  9. @Kevin: Hab es berichtigt

    Michael Kliewe

    25 Mrz 10 at 12:22

  10. Ja okay, aber ein wenn du jetzt theoretisch auch noch ein paar Leerzeichen nach dem <i> hast, dann ist da wieder eins zuviel 😉

    Markus

    25 Mrz 10 at 12:23

  11. Das ist dann ein Fehler des Programmierers.

    Michael Kliewe

    25 Mrz 10 at 12:49

  12. Warum einen zusätzlichen Overhead wenn man ohnehin per GZIP komprimiert?

    Den Vorteil sehe ich noch nicht.

    1) Du entfernst die Leerzeichen etc. dynamisch, also bei jedem Aufruf, was je nach Grösse des Dokuments durchaus Zeit in Anspruch nimmt.
    2) Du komprimierst zusätzlich die gesamte Seite.

    Sehe ich den Vorteil nur nicht oder geht es hier um Machbarkeit? Ich würde es mir eingehen lassen, wenn man statische Seiten hat (vgl. Minify) oder man GZIP abschalten will bzw. nicht zur Verfügung hat.

    Aber so? Oder ist das gezielt für Browser die kein GZIP unterstützen? Dann müsste man aber noch ne Browserweiche einfügen und das ist dann echt zuviel :)

    Rob

    25 Mrz 10 at 13:32

  13. […] Dieser Eintrag wurde auf Twitter von mAtZ, Michael Kliewe erwähnt. Michael Kliewe sagte: Neuer Blogartikel: Zend_View Output Filter: Whitespaces aus HTML entfernen ( http://www.phpgangsta.de/1205 ) […]

  14. Vielen Dank für den Artikel!
    Solche Artikel gefallen mir immer besonder gut.
    Hättest du noch solche Artikel zum Thema Zend Framework?

    Noch eine kleine bitte:
    Könnte man den Code noch so abändern,
    das der Whitespace zwischen pre-Tags nicht entfernt wird?

    David

    25 Mrz 10 at 16:12

  15. @Christian Die Suchmaschinen beachten keine Whitespaces (zumindest kennen ich keinen SEO’ler der dies so vertritt). Insbesondere Yahoo mit Minify und YSlow versucht ja auch das gleiche zu erreichen indem möglichst so wenig wie möglich Daten übertragen werden. Auch die Geschwindigkeit der Seite ist Google (noch) egal.

    Die Frage finde ich auch interessant (Ich formuliere sie nochmal genauer 😉 ): Spart man auch 3-15% Whitespaces wenn man im Nachhinein noch gezippt oder wäre das dann egal (bzw. die Ersparnis minimal)?

    Ansonsten: Super Idee!

    Ulf

    25 Mrz 10 at 18:27

  16. @Rob: Ja, es war eher als einfaches Beispiel gedacht, wie man solche Filter einsetzen kann. Natürlich macht das spezielle Beispiel nur wirklich Sinn wenn man gzip nicht zur Verfügung hat oder seinen Code „unlesbar“ machen will (für Script-Kiddys halt, ihn wieder lesbar zu machen ist kein großes Problem).

    @David: Ich versuche viele Artikel zum Zend Framework zu verfassen, aber nicht immer fallen mir Themen ein. Bin für Vorschläge/Wünsche offen.

    pre-Tags sind ein Problem, das stimmt. Das dürfte nicht so einfach sein. Kann jemand helfen?

    Michael Kliewe

    25 Mrz 10 at 18:38

  17. Nette Idee, könnte man leicht mit Minify, speziell mit der Klasse für HTML verbinden.

    Gruß Patrick

    Patrick

    25 Mrz 10 at 23:47

  18. Habs gestern auch mal durchgetestet anhand einer recht umfangrecihen, interaktiven Adminoberfläche. Das Beispiel ist nicht ernshasft lauffähig. Eingebetteter Javascript Code nud CSS wird zerstört etc.
    Ich habs (wie mittlerweile hier auch schon vorgeschlagen) dann folgendermaßen umgesetzt:

    public function filter($string)
    {
    Zend_Loader_Autoloader::getInstance()->registerNamespace(‚Minify_‘);
    return Minify_HTML::minify($string);
    }

    Damit bleibt die Seite intakt aber die Ersparnis ist gering und steht in keinem Verhältnis zur benötigten Rechenzeit. Jedenfalls nicht bei dynamischen Seiten die rechteabhängig pro Request&User generiert werden.
    Wenn man es statisch cachen kann ist das was anderes, dann würde ich es sofort aktivieren.

    Ich sehe es aber auch eher als nettes Beispiel für die Verwendung von Filtern und insofern muß ich ein Herzliches Dankeschön aussprechen!!!
    Bisher war ich mit Filtern noch nicht in Berührung gekommen und muß sagen ich hab sie bereits lieb gewonnen 😉 und werde damit ein paar Punkte umsetzen können, von denen ich bisher noch nicht wußte wie ich sie anpacken soll – genial! Danke Michael

    Kevin

    26 Mrz 10 at 11:48

  19. Was ist auch z.B. mit -Elementen? Bei mir werden u.a. die Zeilenumbrüche entfernt.

    David

    22 Mrz 11 at 20:03

  20. [] wurde ersetzt.

    David

    22 Mrz 11 at 20:04

  21. >pre< wurde ersetzt.

    David

    22 Mrz 11 at 20:05

Leave a Reply

You can add images to your comment by clicking here.