Cachen von Seiten
=================

Beim Cachen von Seiten wird der Inhalt einer ganzen Seite gecacht. Dies kann
an verschiedenen Stellen geschehen. Der Clientbrowser kann zum Beispiel
bereits betrachtete Seiten für einen begrenzten Zeitraum cachen, indem man
einen passenden Seitenheader wählt. Auch die Webanwendung selbst kann den
Inhalt einer Seite im Cache speichern. In diesem Kapitel sehen wir uns
letzeren Ansatz näher an.

Das Cachen einer Seite kann als Spezialfall des [Cachens von
Fragmenten](/doc/guide/caching.fragment) betrachtet werden. Da der
Inhalt einer Seite oft mittels Anwendung eines Layouts auf einen View 
erzeugt wird, funktioniert es nicht, wenn man einfach
[beginCache()|CBaseController::beginCache] und
[endCache()|CBaseController::endCache] im Layout aufruft. Das liegt daran, da
das Layout innerhalb von [CController::render()] erst angewendet wird, NACHDEM der
View-Inhalt bestimmt wurde.

Um eine ganze Seite zu cachen, sollte man die Ausführung derjenigen Action
überspringen, die den Seiteninhalt erzeut. Um dies zu erreichen, kann man [COutputCache] als
[Filter](/doc/guide/basics.controller#filter) für eine Action verwenden.
Der folgende Code zeigt, wie man den Cachefilter konfiguriert:

~~~
[php]
public function filters()
{
	return array(
		array(
			'COutputCache',
			'duration'=>100,
			'varyByParam'=>array('id'),
		),
	);
}
~~~

Bei obige Filterkonfiguration würde den Filter auf alle Actions des
Controllers anwenden. Über den Plus-Operator, kann man ihn
auf eine oder wenige Actions beschränken. Nähere Informationen hierzu finden
sich unter [Filter](/doc/guide/basics.controller#filter).

> Tip|Tipp: Man kann [COutputCache] deshalb als Filter verwenden, weil er
[CFilterWidget] erweitert, was bedeutet, dass er sowohl ein Widget, als auch ein
Filter ist. Tatsächlich ähneln sich die Funktionsweisen eines Widgets und
eines Filters: Ein Widget (Filter) beginnt, bevor der eingebettete Inhalt
(Action) ausgewertet wird und endet, nachdem dieser Inhalt (Action)
ausgewertet wurde.

HTTP Caching
------------
Zusätzlich zum Cachen der Rückgabe einer Action ist es seit Yii 1.1.11 möglich,
[CHttpCacheFilter] zu verwenden. Dieser Filter vereinfacht das Setzen der Header,
welche nötig sind um einem Client mitzuteilen das der Inhalt einer Seite nicht modifiziert wurde.
Auf diese Weise muss der Server den Inhalt der Seite nicht erneut übertragen.
Die Konfiguration von [CHttpCacheFilter] ist der von [COutputCache] ähnlich:
~~~
[php]
public function filters()
{
    return array(
        array(
            'CHttpCacheFilter + index',
            'lastModified'=>Yii::app()->db->createCommand("SELECT MAX(`update_time`) FROM {{post}}")->queryScalar(),
        ),
    );
}
~~~
Der obige Filter wird den `Last-Modified`-Header auf das Datum der letzten Änderung am Beitrag(Post) setzen.
Alternativ kann [CHttpCacheFilter::lastModifiedExpression] benutzt werden, 
um den `Last-Modified`-Header durch einen PHP-Ausdruck zu setzen. 


> Tip|Tipp: Sowohl [CHttpCacheFilter::lastModifiedExpression] als auch 
[CHttpCacheFilter::lastModified] können entweder einen UNIX-Timestamp oder einen String mit einem für Menschen
lesbaren Datum verwenden, solange dieser mithilfe von [strtotime()](http://php.net/manual/function.strtotime.php) 
geparst werden kann. Es ist keine weitere Umwandlung nötig.

Der "Entity Tag" (kurz: `ETag`) Header kann auf ähnliche Weise mit Hilfe von 
[CHttpCacheFilter::etagSeed] und [CHttpCacheFilter::etagSeedExpression] gesetzt werden. 
Sie werden serialisiert (so ist es möglich, entweder einen einzelnen String oder ein gesamtes Array zu nutzen) 
und benutzt um den Base64 codierten, sha1 gehashten und mit Anführungszeichen
versehenen Wert des `ETag`-Headers zu erstellen. Diese Methode unterscheidet sich 
vom [Apache Webserver](http://httpd.apache.org) ist jedoch vollständig konform zu den 
dazugehörigen RFC und hat sich als für besser geeignet in einem Framework gezeigt.


> Note|Zu beachten: Um [RFC 2616, section 13.3.4](http://tools.ietf.org/html/rfc2616#section-13.3.4)
zu folgen, sendet [CHttpCacheFilter] sowohl den `ETag` *als auch* den `Last-Modified`-Header,
falls beide erstellt werden können. Beide werden zur Cachevalidierung genutzt, wenn sie vom Client gesendet werden.

Da "Entity Tags" gehasht werden erlauben sie komplexere und/oder präzisere Möglichkeiten 
als der `Last-Modified`-Header. Zum Beispiel kann ein ETag geändert werden, falls das Theme der Seite
gewechselt wird.

> Tip|Tipp: Aufwendige Bedingungen für [CHttpCacheFilter::etagSeedExpression] können den 
Nutzen von [CHttpCacheFilter] untergraben und einen unnötigen Mehraufwand verursachen, da sie bei 
jeder Anfrage erneut verarbeitet werden müssen.
Es sollte eine einfache Bedingung gefunden werden, die den Cache, 
falls der *Inhalt* der Seite geändert wurde, invalidiert.

### Auswirkungen auf die Suchmaschinenoptimierung (SEO)
Die meisten Suchmaschinen neigen dazu Cacheheader zu beachten. Da einige Crawler ein Limit haben, 
wie viele Seiten pro Domain sie in einer bestimmten Zeitspanne
verarbeiten, kann das Benutzen von Cacheheadern das Indizieren der Seite verbessern, 
da die Anzahl der zu verarbeiteten Seiten reduziert wird.
<div class="revision">$Id$</div>
