Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Geleitwort des Fachgutachters
Vorwort
1 Einleitung
2 Einführung in eZ Components
3 Die Applikationsbasis
4 Fehlerbehandlung und Debugging
5 Konfiguration
6 Datenbankanbindung
7 ORM mit PersistentObject
8 Template
9 Übersetzung
10 Benutzereingaben validieren
11 Authentifizierung
12 Bildverarbeitung
13 Archive und Dateien
14 Mail
15 Logging
16 Diagramme
17 Feeds und Caching
18 Setup
A Inhalt der Buch-CD
Stichwort
Download: - ZIP, ca. 2,7 MB
Ihre Meinung?
<< zurück | Galileo Computing / <openbook> /eZ Components | vor >>
eZ Components von Tobias Schlitt, Kore Nordmann Das Entwickler-Handbuch
eZ Components geb., mit CD 454 S., 39,90 Euro Galileo Computing ISBN 978-3-8362-1073-7 |
| 2 Einführung in eZ Components
|  | 2.1 eZ Components installieren
|  |  | 2.1.1 Versionierung
|  |  | 2.1.2 Installation per PEAR
|  |  | 2.1.3 Das Gesamtpaket herunterladen
|  |  | 2.1.4 SVN
|  | 2.2 Autoload konfigurieren
|  |  | 2.2.1 eZ Components Autoload einschalten
|  |  | 2.2.2 Interna des eZ Components Autoloads
|  |  | 2.2.3 Eigenes Autoload einbinden
|  |  | 2.2.4 Preloading
|  | 2.3 Weitere Bestandteile der Base-Komponente
|  |  | 2.3.1 Optionen-Klassen
|  |  | 2.3.2 Exceptions
|  |  | 2.3.3 ezcBaseFeatures
|  |  | 2.3.4 Lazy-Initialization
|  | 2.4 Dokumentation
|  |  | 2.4.1 API-Dokumentation
|  |  | 2.4.2 Anleitungen
|  |  | 2.4.3 Mitgeliefertes
|  |  | 2.4.4 Beispielapplikationen und Artikel
|  |  | 2.4.5 Support
|  | 2.5 Selbst etwas beisteuern
|  |  | 2.5.1 Fehler melden
|  |  | 2.5.2 Patches bereitstellen und Dokumentation verbessern
|  |  | 2.5.3 Eigene Komponenten beisteuern
|  |  | 2.5.4 Contributor-License-Agreement
## 2.3 Weitere Bestandteile der Base-Komponente Neben dem Autoload-Mechanismus stellt die Base-Komponente noch weitere Basisfunktionalitäten bereit, die von anderen Komponenten genutzt werden. Hierzu zählen nicht nur die Optionen-Klassen, die beinahe jede Komponente mitbringt, sondern auch die Basis-Exceptions, die entweder von Paketen direkt genutzt oder zur Nutzung erweitert werden. Schließlich stellt die Klasse ezcBaseFeatures Mechanismen bereit, um zu testen, ob in der aktuellen Umgebung ein bestimmtes Feature verfügbar ist, damit Komponenten entsprechend darauf reagieren können. Zum Beispiel kann hiermit festgestellt werden, ob das zugrunde liegende System das Konzept der symbolischen Links (Symlinks) unterstützt, oder ob Dateien kopiert werden müssen, um ein ähnliches Verhalten zu erreichen. ### 2.3.1 Optionen-Klassen Typischerweise lässt sich das Verhalten eines Objekts über verschiedene Einstellungsparameter beeinflussen. Zum Beispiel wird einem Objekt, das eine Tabelle repräsentiert, mitgeteilt, wie viele Spalten und Zeilen die Tabelle haben soll, eventuell wie breit und hoch diese sind, wie deren Inhalt formatiert werden soll und vieles mehr. Insbesondere Klassen aus einer Bibliothek lassen sich in ihrem Verhalten meist stark mittels Konfigurationsparametern beeinflussen und an die eigenen Bedürfnisse anpassen. #### Zwei Typen von Konfigurationen In eZ Components werden zwei Typen von Konfigurationsparametern für ein Objekt unterschieden: Settings (Einstellungen) und Options (Optionen). Der Unterschied zwischen diesen beiden Begriffen mag nicht auf Anhieb klar sein, macht aber durchaus Sinn: Mit Settings werden Einstellungen bezeichnet, die ein Objekt unbedingt benötigt, da es ohne diese Parameter nicht funktionsfähig wäre. Daneben ist es üblich, dass Settings beim Erzeugen eines Objekts einmalig gesetzt werden und in dessen weiteren Lebenszyklus nicht mehr geändert werden können. Options hingegen sind von vornherein mit einem sinnvollen Standardwert, dem Default-Value, ausgerüstet und müssen daher nicht zwingend geändert werden. Optionen sind also optional. Des Weiteren können Optionen zu jedem Zeitpunkt im Lebenszyklus eines Objekts geändert werden, sodass das Verhalten somit jederzeit änderbar ist. In den Klassen der eZ Components werden Settings beim Erzeugen eines Objekts an den Konstruktor oder den jeweils verfügbaren Erzeugungsmechanismus übergeben. Sie werden als normale Methoden-Parameter übergeben und benötigen kein gesondertes Objekt zur Verpackung – ganz im Gegensatz zu Optionen. Zwar können diese beim Erzeugen des Objekts ebenfalls über einen Parameter mitgegeben werden, dies ist jedoch nicht zwingend nötig. Bei der Konstruktion eines Objekts werden Optionen meist mit Hilfe eines Arrays definiert, was auf die Anfangsphase des eZ Components-Projekts zurückzuführen ist, in der Optionen komplett in Array-Strukturen verwaltet wurden. Doch schon nach kurzer Zeit wurde dieser Mechanismus durch eine eigene Sorte von Objekten abgelöst, deren Klasse von der Klasse ezcBaseOptions erbt. #### Optionen-Klassen verwenden Die ezcBaseOptions-Klasse stellt ein einheitliches Interface für die Optionen-Klassen aller Komponenten bereit und bildet eine Basis, auf der diese sehr einfach und schnell implementiert werden können. In der Hauptsache implementiert die Basisklasse die Interzeptoren __get(), __set() und __isset() sowie einen generischen Konstruktor und die Methoden des ArrayAccess-Interfaces (siehe Kästen). Letzteres allerdings nur aus Kompatibilitätsgründen zu den vorher verwendeten Optionen-Arrays. Für Sie als Benutzer stellt sich die API der Optionen-Klassen sehr intuitiv dar, denn Sie greifen lediglich auf die Attribute eines Optionen-Objekts zu und setzten dort die gewünschten Werte ohne zu bemerken, dass intern die Interzeptor-Methoden verwendet werden, um jeden Ihrer Schritte zu überprüfen. Die Bereitstellung dieses intuitiven und einfachen Benutzer-Interfaces ist eines der verbreitetsten API-Konzepte in eZ Components und wurde Virtual Properties getauft.
Interzeptoren
Interzeptoren, auch Overloading genannt, wurden bereits in PHP Version 4 implementiert, verließen aber in dieser Version nie den Status experimentell. Unter der Bezeichnung verbergen sich sogenannte magische Methoden, die von einer Klasse implementiert werden können, um den Zugriff auf nicht existente oder nicht zugreifbare Methoden und Attribute abzufangen. Mit Hilfe von Interzeptoren kann verhindert werden, dass PHP direkt einen Fehler erzeugt, oder Attribute kommentarlos neu erzeugt werden. Die Behandlung entsprechender Elemente kann beeinflusst werden.
Für Attribute sind hierbei die noch folgenden Methoden zuständig. Als Wert des Parameters $propertyName wird vom PHP-Interpreter der Name des Attributs übergeben, auf das nicht zugegriffen werden konnte. __get( $propertyName ) Diese Methode wird aufgerufen, wenn ein Attribut, auf das lesend zugegriffen werden soll, nicht existiert oder wenn es, falls der Zugriff von außerhalb des Klasse erfolgte, als privat oder geschützt deklariert wurde. Der Rückgabewert dieser Methode wird dem ursprünglichen Aufruf als Wert des Attributs zurückgegeben. __set( $propertyName, $propertyValue ) Analog zu __get() wird die Methode __set() beim Schreibzugriff auf ein Attribut aufgerufen. Der Parameter $propertyValue enthält dabei den Wert, der zugewiesen werden sollte. Eine Rückgabe aus dieser Methode wird komplett ignoriert. __isset( $propertyName ) Die PHP-Funktion isset() zeigt ein recht spezielles Verhalten, denn normalerweise wird beim Zugriff auf eine nicht existierende Variable ein Fehler erzeugt. Bei isset() ist dies nicht der Fall, denn die Funktion dient dazu festzustellen, ob eine Variable existiert. Da der PHP-Interpreter nicht wissen kann, welche Attribute durch __get() und __set() abgedeckt werden, ist es konsequent, für isset() ebenfalls einen Interzeptor bereitzustellen. Die Rückgabe aus dieser Methode muss ein boolescher Wert, also true oder false, sein. Neben den hier vorgestellten Interzeptor-Methoden existieren noch weitere für Attribute sowie __call() für nicht existierende Methoden. Mehr zum Thema Overloading erfahren Sie im PHP-Manual unter der Adresse http://php.net/manual/en/language.oop5.overloading.php.
Das ArrayAccess Interface
ArrayAccess ist ein Bestandteil der Standard-PHP-Library (SPL), einer Standarderweiterung von PHP, die mit PHP 5 eingeführt wurde, um eine Vielzahl interessanter, objektorientierter Konstrukte aufzunehmen. Das Interface erlaubt es, auf Objekte zuzugreifen als seien sie Arrays. Allerdings bedient dieses Interface nicht den Zugriff mittels foearch oder count(), sondern lediglich die reine Array-Semantik von PHP, also Zugriffe der Form $object[»key«]. Für die Verwendung von Objekten mit der count()-Funktion und dem foreach-Statement existieren es weitere Interfaces.
Die Methoden des ArrayAccess Interface lauten: offsetGet($offset) Diese Methode wird beim lesenden Zugriff auf einen Array-Schlüssel aufgerufen, also zum Beispiel bei echo $object[$offset];. Ein aus der Methode zurückgegebener Wert wird entsprechend an den Aufruf weitergeleitet. offsetSet($offset, $value) Analog zu offsetGet() wird diese Methode verwendet, um die Zuweisungen von Werten zu emulieren. Dem Schlüssel $offset wird dabei der Wert $value zugewiesen, also in Array-Semantik: $object[$offset] = $value;. Eine Rückgabe ist nicht erforderlich und wird ignoriert. offsetExists($offset) / offsetUnset($offset) Entsprechend simuliert diese Methode den Zugriff mittels der Funktionen isset() und unset(), wie Sie es bereits von der Overloading-Methode __isset() im Kasten „Interzeptoren“ her kennen. Weitere Informationen zu SPL und den enthaltenen Interfaces und Basisklassen finden Sie unter http://www.php.net/~helly/php/ext/spl/. Zunächst folgt an dieser Stelle ein Beispiel zur Benutzung von Optionen:
    <?php
    $progress = new ezcConsoleProgressbar(
        $out,
        100,
        array( 'step' => 5 )
    );
    $progress->options->emptyChar = '-';
    $progress->options["progressChar"] = '>';
    $progress->options->step = 10;
    ?>
Listing 2.6 Benutzung von Optionen In diesem Beispiel wird eine neue Instanz der Klasse ezcConsoleProgressbar erzeugt, die einen Status-Balken auf der Konsole darstellen kann. Mehr über diese Klasse erfahren Sie in Kapitel 18, »Setup«, welches sich mit der ConsoleTools-Komponente befasst. Dem Konstruktor der Klasse werden zwei Settings und ein Array von Optionen als Parameter übergeben. Die Variable $out enthält in diesem Beispiel eine Instanz von ezcConsoleOutput und der Wert 100 bestimmt die absolute Länge des Balkens in Zeichen. Beide Werte können später nicht mehr verändert werden, da es sich um Einstellungen und nicht um Optionen handelt. Dies ist sinnvoll, denn wenn der Status-Balken einmal angezeigt wurde und anschließend die Größe geändert würde, käme es zu unschönen Effekten in der Darstellung. Das Optionen-Array enthält lediglich die Option $step, wobei an dieser Stelle nicht interessiert, was diese Option bewirkt. Interessant hingegen ist, dass intern in ezcConsoleProgressbar eine neue Instanz von ezcConsoleProgressbarOptions erzeugt wird, der das Optionen-Array übergeben wird. Die nächsten drei Zeilen zeigen, wie Optionen nach der Erzeugung des Objekts geändert werden können. Bei allen Klassen von eZ Components, die eine zugehörige Optionen-Klasse besitzen, können Optionen auf die dargestellte Weise manipuliert werden. Das heißt, es existiert in den entsprechenden Objekten ein Attribut namens $options, das den direkten Zugriff auf die Optionen gestattet. Zeile sechs zeigt den Zugriff auf Optionen mittels der überladenen Attribute. Die zweite Variante auf Optionen zuzugreifen wird in der folgenden Zeile dargestellt, nämlich über das ArrayAccess-Interface, wie Sie es vom Zugriff auf echte Arrays gewohnt sind. Wie bereits erwähnt, dient diese Art des Zugriffs lediglich der Abwärtskompatibilität; der Zugriff über Attribute wird empfohlen. Die letzte Zeile des Beispiels zeigt nochmal den Zugriff über Attribute, diesmal auf die Option $step, die bereits im Konstruktor gesetzt wurde und hier vom Wert 5 auf 10 geändert wird. #### Virtual Properties Nachdem Sie nun den Zugriff auf Optionen kennengelernt haben, soll das Konzept der Virtual Properties anhand der Optionen-Klasse näher erläutert werden. Zum einen, weil es in eZ Components an sehr vielen Stellen verwendet wird. Zum anderen empfinden wir diese Methode zur Bildung einer intuitiven aber sicheren API als äußerst angenehm und möchten Ihnen zeigen, wie Sie selbst auf diese Art programmieren können.
    abstract class ezcBaseOptions implements ArrayAccess
    {
        protected $properties;
        public function __construct( array $options = array() )
        {
            foreach ( $options as $option => $value )
            {
                $this->__set( $option, $value );
            }
        }
        public function __get( $propertyName )
        {
            if ( $this->__isset( $propertyName ) === true )
            {
                return $this->properties[$propertyName];
            }
            throw new ezcBasePropertyNotFoundException(
                $propertyName
            );
        }
        abstract public function __set(
            $propertyName,
            $propertyValue
        );
        public function __isset( $propertyName )
        {
            return array_key_exists(
                $propertyName,
                $this->properties
            );
        }
    // ... ArrayAccess methods...
    }
Listing 2.7 Virtuelle Eigenschaften Die Methoden des ArrayAccess-Interface wurden hier ausgeblendet. Sie leiten lediglich auf die entsprechenden Interzeptor-Methoden weiter und erfüllen keinen zusätzlichen Zweck außer der erwähnten Abwärtskompatibilität. Des Weiteren wurde die Methode merge() ausgelassen, welche dazu dient, die Werte zweier Optionen-Objekte zu mischen, was aber hier ebenfalls nicht von Interesse ist. Die Klasse ezcBaseOptions verfügt über ein einziges Attribut namens $properties, das von außen nicht zugreifbar ist. Aus diesem Grund leitet der PHP-Interpreter sämtliche Attributzugriffe auf die entsprechenden magischen Methoden um. Man mag zuerst denken, dass es dann sinnvoll wäre, die entsprechenden Attribute einfach als privat oder geschützt zu deklarieren. Dann jedoch würden Zugriffe von Methoden innerhalb der Klasse direkt auf diese Attribute zugreifen und nicht den Umweg über die Interzeptoren gehen. Der Grund, auch interne Aufrufe umzuleiten, ist, dass in den magischen Methoden jeweils die Existenz des entsprechenden Attributs überprüft und zusätzlich beim Schreibzugriff der Typ und die Plausibilität des Werts der Zuweisung validiert werden. Falls unbedingt notwendig, können die Optionen direkt über das $properties-Array manipuliert werden – dies sollte jedoch gewöhnlich vermieden werden. Mit Hilfe dieser Technik ist es möglich, dass jene Prüfungen an nur einer zentralen Stelle der Klasse erfolgen müssen und an allen weiteren Stellen die gewohnte API für den Zugriff auf die Attribute verwendet werden kann. Daher der Name Virtual Properties. Ähnliche Konzepte existieren ebenfalls in Sprachen wie beispielsweise C#. Als Erstes soll nun der Konstruktor der Klasse begutachtet werden, der generisch für jede Optionen-Klasse implementiert ist und nur im Ausnahmefall überschrieben wird. Die Methode nimmt optional ein Array von Optionswerten entgegen und weist diese innerhalb der foreach-Schleife den Attributen zu. Sie sehen also, dass auch in diesem Fall keine direkte Zuweisung erfolgt, sondern der Umweg über __set() gewählt wird und somit die Werte des Arrays auf ihre Gültigkeit überprüft und erst anschließend bei Korrektheit zugewiesen werden. Die Methode __set() muss an dieser Stelle allerdings explizit aufgerufen werden, da sonst von einem Benutzer versehentlich das Array $properties überschrieben werden könnte. Die __get() Methode überprüft zunächst mittels der Overloading-Methode __isset(), ob die entsprechende Virtual Property existiert. Ist dies der Fall, wird ihr Wert zurückgeben, im anderen Fall wirft die Methode eine Exception vom Typ ezcBasePropertyNotFoundException. Näheres zum Thema Exceptions können Sie im nächsten Abschnitt 2.3.2, »Exceptions«, erfahren. Praktisch ist an dieser Stelle, dass mit dem Umweg über __get() eine unschöne Angewohnheit von PHP überwunden wird: Denn normalerweise wird beim lesenden Zugriff auf ein nicht existierendes Attribut lediglich ein Fehler von Typ E_NOTICE erzeugt. Insbesondere wenn PHP so konfiguriert ist, dass dieser Fehlertyp nicht angezeigt wird, können Tippfehler zu wahren Debug-Eskapaden führen. Eine Exception, die nicht gefangen wird, resultiert jedoch in einem fatalen Fehler. Die Methode __isset()behebt ein weiteres Manko von PHP, indem sie ihrerseits anstatt isset() auf dem Array $properties zu verwenden, über die PHP-Funktion array_key_exists() überprüft, ob der gesuchte Schlüssel existiert. Für den Fall, dass der Schlüssel zwar existiert, aber einen Wert vom Typ null hat, gibt die Funktion isset() den Wert false zurück, array_key_exists() hingegen true. Somit resultiert der Aufruf isset($object->property); im erwarteten Ergebnis true, falls die entsprechende Virtual Property existiert. Eine Überprüfung auf null ist trotzdem weiterhin mittels $object->property === null möglich. Wie Sie sehen, ist es mittels der Interzeptoren möglich, nicht nur eine komfortable API zu schaffen, sondern auch kleinere Unreinheiten des PHP-Interpreters auszubügeln. Außerdem erhalten Sie ein Mittel, welches in manchen Programmiersprachen nur mittels eigener getProperty()-/setProperty()-Methoden gelöst werden kann, womit der intuitive Attributzugriff nicht mehr gegeben ist. #### Beispieloptionen Schließlich bleibt noch zu zeigen, was eine Komponente noch selbst implementieren muss, um eine voll funktionsfähige Optionen-Klasse zu erhalten. Am bereits anfänglich gezeigten Beispiel von ezcConsoleProgressbarOptions soll dies verdeutlicht werden:
    class ezcConsoleProgressbarOptions extends ezcBaseOptions
    {
        protected $properties = array(
            'barChar'         => "+",
            'emptyChar'       => "-",
            // ... more default values...
            'width'           => 78,
            'actFormat'       => '%.0f',
            'maxFormat'       => '%.0f',
        );
       public function __set( $key, $value )
        {
            switch ( $key )
            {
                case "barChar":
                // ...
                case "maxFormat":
                    if ( is_string( $value ) === false
                        || strlen( $value ) < 1 )
                    {
                        throw new ezcBaseValueException(
                            $key,
                            $value,
                            'string, not empty'
                        );
                    }
                    break;
                case "width":
                    if ( !is_int( $value ) || $value < 5 )
                    {
                        throw new ezcBaseValueException(
                            $key,
                            $value,
                            'int >= 5'
                        );
                    }
                    break;
                case "redrawFrequency":
                case "step":
                    if ( ( !is_int( $value ) && !is_float( $value ) )
                        || $value < 1 )
                    {
                        throw new ezcBaseValueException(
                            $key,
                            $value,
                            'int > 0'
                        );
                    }
                    break;
                default:
                    throw new ezcBasePropertyNotFoundException(
                       $key
                    );
            }
            $this->properties[$key] = $value;
        }
    }
Listing 2.8 Implementierung einer Optionen-Klasse Innerhalb der Klasse wird zunächst das Array $properties aus ezcBaseOptions überschrieben, um festzulegen, welche Virtual Properties existieren, und diesen sinnvolle Standardwerte mitzugeben. Der Übersichtlichkeit halber wurden an dieser Stelle einige Attribute ausgeblendet. Die einzige Methode, die implementiert werden muss, ist __set(), welche in ezcBaseOptions abstrakt deklariert wurde. Sie erinnern sich, dass zum Beispiel im Konstruktor von ezcBaseOptions auf __set() zugegriffen wird, denn innerhalb dieser Methode sollen die Typen und Werte der Virtual Properties validiert werden. Diese Validierung wird pragmatisch über ein großes switch-Statement, in dem die Attribute kategorisiert und entsprechend ihrer Kategorie validiert werden, gelöst. Zum Beispiel muss sowohl $barChar als auch $maxFormat vom Typ String sein und mindestens eine Länge von einem Zeichen aufweisen. Ist der Wert für ein zu setzendes Attribut nicht gültig, wird eine Exception vom Typ ezcBaseValueException erzeugt und mit entsprechenden Daten versehen, sodass eine einheitliche und sprechende Fehlermeldung entsteht. Wird ein nicht existierendes Attribut zum Schreiben angefragt, erzeugt dies, wie Sie schon von __get() wissen, eine ezcBasePropertyNotFoundException. Kommt der Programmfluss am Ende des switch-Statements an, so sind die nötigen Validierungen erfolgreich verlaufen und die Zuweisung erfolgt. In diesem Beispiel nicht zu sehen sind sogenannte Read-Only-Properties, die ebenfalls mit Hilfe der gezeigten Technik der Virtual Properties realisiert werden können. Statt einer ezcBasePropertyNotFoundException wird in eZ Components dann eine ezcBasePropertyPermissionException geworfen, um anzuzeigen, dass das gewünschte Attribut zwar existiert, der Schreibzugriff aber nicht erlaubt ist. Ein Beispiel für eine Read-Only-Property können Sie sich in Abschnitt 3.3.1, »Grundstruktur«, näher ansehen, da dieses Konzept im GP-Blog Verwendung findet. Sie wissen nun, welches ausgeklügelte Konzept hinter der Klasse ezcBaseOptions steckt, mit dem nicht nur die Erstellung neuer Optionen-Klassen sehr einfach ist, sondern durch die Verwendung von Virtual Properties auch die Verwendung der Optionen-Objekte sehr komfortabel erfolgt. Das Konzept der Virtual Properties ist häufig in eZ Components anzutreffen, da es zum einen die intuitive Verwendung von Attributen erlaubt, zum anderen aber die Vorteile der aus anderen Sprachen bekannten Getter- und Setter-Methoden implementiert. Nicht nur die zentrale Überprüfung von Typen und Werten ist möglich, auch kleine Unreinheiten im Verhalten des PHP-Interpreters werden so beseitigt. ### 2.3.2 Exceptions Ein weiteres Feature, das die Base-Komponenten allen anderen Komponenten bereitstellt, zeigt sich in standardisierten Exceptions. Die wichtigste Exception-Klasse ist die ezcBaseException, von welcher alle weiteren Exceptions in eZ Components, eventuell über mehrere Ebenen, erben. Sollten Sie also, obwohl dies meist als unschön empfunden wird, alle Exceptions aus eZ Components auf einen Schlag abfangen wollen, können Sie im catch-Block einfach auf ezcBaseException hin prüfen. Neben diesem Seiteneffekt der ezcBaseException sorgt diese Exception dafür, dass Exception-Meldungen in jeder Umgebung korrekt angezeigt werden. Zur Anzeige im Browser findet dazu eine Entwertung der HTML-Spezialzeichen statt. Sollten Sie einmal auf die originale Nachricht einer Exception zugreifen müssen, zum Beispiel, um diese zu loggen, so erhalten Sie über das öffentliche Attribut $originalMessage Zugriff darauf. Einige Exceptions der Base-Komponente werden von anderen Komponenten geworfen, ohne sie zu erweitern. Zum Beispiel wenn der Zugriff auf eine Virtual Property scheitert, was Sie bereits in Abschnitt 2.3.1, »Optionen-Klassen«, gesehen haben. Diese Exceptions werden nun der Reihe nach kurz vorgestellt. #### Exceptions beim Dateizugriff Einige Komponenten definieren für spezielle Dateizugriffe eigene Exceptions, die allerdings alle von ezcBaseFileException erben. Für die gängigsten Operationen stellt die Base-Komponente bereits generische Exceptions bereit, die von den einzelnen Komponenten direkt verwendet werden: ezcBaseFileException bildet die abstrakte Grundlage aller datei-bezogenen Exceptions. Sie definiert fünf Klassen-Konstanten, welche die Art des Zugriffs repräsentieren, bei dem der Fehler aufgetreten ist. Dies dient vorrangig der Erzeugung einheitlicher Exception-Meldungen. Folgende Konstanten stehen bereit: READ für lesenden Zugriff WRITE bei Schreiboperationen EXECUTE beim Versuch, eine Datei auszuführen CHANGE bei sonstigen Änderungen an der Datei REMOVE für das Löschen der Datei. ezcBaseFileIoException erscheint, falls ein Fehler während einer Lese- oder Schreiboperation auftritt. Sollten Sie eine solche Exception erhalten, ist es ratsam, möglichst schnell das betroffene Dateisystem zu überprüfen. Eine solche Exception tritt auf, wenn eine Datei erfolgreich geöffnet werden konnte, die eigentliche Aktion aber misslang. Dies deutet oft auf eine volle oder gar defekte Festplatte hin. ezcBaseFileNotFoundException wird geworfen, wenn eine benötigte Datei nicht gefunden werden konnte. ezcBaseFilePermissionException tritt auf, wenn benötigte Zugriffsrechte verweigert wurden, zum Beispiel das Recht, in die Datei zu schreiben, wenn Änderungen gespeichert werden sollen. #### Property- und Typprüfungsexceptions Einige der Exceptions aus diesem Bereich haben Sie bereits in Abschnitt 2.3.1, »Optionen-Klassen«, kennengelernt, als der Mechanismus der Virtual Properties anhand der Klasse ezcBaseOptions erläutert wurde. Hier noch einmal eine Übersicht: ezcBasePropertyNotFoundException weist darauf hin, dass die gewünschte Virtual Property nicht gefunden wurde. Meist resultiert diese Exception aus einem Tippfehler im Namen eines Attributs. ezcBasePropertyPermissionException wird geworfen, wenn der Zugriff auf eine Virtual Property gescheitert ist, da die Art des Zugriffs – lesend oder schreibend – nicht gestattet ist. Welche Zugriffsart gestattet ist, wird in der Exception-Meldung mitgeteilt. ezcBaseValueException zeigt an, dass der Wert, den Sie einem Parameter oder einer Virtual Property zuweisen wollen, ungültig ist. Den gültigen Typ sowie den Wertebereich finden Sie hier ebenfalls in der Exception-Meldung. #### Sonstige Exceptions ezcBaseExtensionNotFoundException wird erzeugt, wenn eine benötigte PHP-Extension nicht vorhanden ist. ezcBaseInvalidParentClassException wird von Komponenten geworfen, welche benutzerdefinierte Klassen für eine Aufgabe verwenden können, bei denen die übergebene Klasse oder das übergebene Objekt aber nicht den Richtlinien entspricht. Dies kann entweder bedeuten, dass die korrekte Basisklasse nicht erweitert oder ein benötigtes Interface nicht implementiert wird. Jede Komponente implementiert zusätzlich weitere Exception-Klassen, um spezielle, komponentenspezifische Ausnahmesituationen darzustellen. Exceptions sind, wie alle anderen Klassen von eZ Components, bis ins Detail dokumentiert und erlauben Ihnen über aussagekräftige Fehlermeldungen das schnelle Erkennen und Beheben von Fehlern. ### 2.3.3 ezcBaseFeatures Die Klasse ezcBaseFeatures steht allen Komponenten zur Verfügung, um auf benötigte Features, wie PHP-Erweiterungen oder Betriebssystemfunktionen, hin zu prüfen. Fehlt das entsprechende Feature, kann die Komponente entweder auf eine Ausweichimplementierung verzweigen oder eine entsprechende Exception erzeugen. Zu diesem Zweck werden folgende statischen Methoden bereitgestellt: supportsLink()/supportsSymLink() Diese beiden Methoden überprüfen, ob das verwendete Betriebssystem das Konzept der Hardlinks (also echte Datei-Links) oder Symlinks unterstützt. Benötigt wird dies zum Beispiel in der Archive-Komponente, die auf das Kopieren von Dateien ausweicht, falls Windows als Betriebssystem vorliegt, da dessen Dateisystem keine der beiden Link-Varianten funktionierend unterstützt. supportsUserId() Ebenfalls für Betriebssystemabstraktionen wird die Methode supportsUser Id() genutzt, die überprüft, ob die Möglichkeit gegeben ist, die aktuelle Benutzer-ID mittels der PHP-Posix-Funktionen zu ermitteln. [http://php.net/posix ] hasImageConvert()/getImageConvertExecutable() Die ImageConversion-Komponente unterstützt unter anderem das Grafik-Paket ImageMagick [http://imagemagick.org/ ] zur Manipulation von Bildern, weshalb diese Methoden es ermöglichen, den Pfad der benötigten Programmdatei zu ermitteln. Diese hat den Namen convert auf Unix-Systemen beziehungsweise convert.exe unter Windows. Die Methoden hasImageIdentify() und getImageIdentifyExecutable() ermöglichen dies analog für das Programm identify respektive identify.exe, welches ebenfalls in ImageMagick enthalten ist und von der ImageAnalysis-Komponente verwendet werden kann. Generisch nach einem Programm suchen, lässt sich mittels der Methode findExecutableInPath(). hasExtensionSupport() Sie ermöglicht es zu überprüfen, ob eine spezielle PHP-Erweiterung ab einer bestimmten Version installiert ist. Dies ist beispielsweise wichtig in der UserInput-Komponente, da für die darunterliegende filter-Erweiterung [http://php.net/filter ] in PHP 5.2 die API geändert wurde und diese Versionsnummer nun überprüft werden muss. hasFunction()/classExists() Während die Methode hasFunction() lediglich auf die PHP-eigene Funktion function_exists() [http://php.net/function_exists ] umleitet, ermöglicht es classExists() zu testen, ob eine Klasse mit gegebenem Namen existiert, ohne dass beim Fehlversuch, diese mittels Autoload zu laden, eine Exception auftritt. os() Die Methode os() ermittelt das verwendete Betriebssystem und gibt einen vereinheitlichten Namen zurück, um generelle Unterscheidungen diesbezüglich zu treffen. Der Code der Klasse ezcBaseFeatures ist zwar nicht sonderlich lang, aber die implementierten Features sind durchaus sinnvoll, wenn es darum geht, plattformunabhängige Applikationen zu entwickeln. Eventuell können Sie diese Funktionalitäten gebrauchen. ### 2.3.4 Lazy-Initialization Häufig passiert es in großen Applikationen, dass Komponenten zwar an vielen unterschiedlichen Stellen benötigt werden, an den meisten Stellen aber nicht alle Komponenten zusammen zum Einsatz kommen. Trotzdem werden diese akut nicht benötigten Komponenten an zentraler Stelle konfiguriert und somit instanziiert. Das Resultat ist ein Overhead an Ausführungszeit und Speicher, der durch die nicht verwendeten Objekte entsteht. Um hier Abhilfe zu leisten, unterstützen eZ Components ein Konzept namens Lazy-Initialization. Dieses Verfahren zum Konfigurieren von Objekten erlaubt es Ihnen, Konfigurationen für bestimmte Singleton-Instanzen (siehe Kasten »Das Singleton-Entwurfsmuster«) anzulegen, ohne die betroffenen Instanzen direkt erzeugen zu müssen. Bei der ersten Verwendung des Singleton-Mechanismus für ein Objekt wird die Instanz automatisch im Hintergrund mit korrekter Konfiguration erzeugt. Objekte werden also nur noch bei ihrer Verwendung erzeugt und konfiguriert, womit der genannte Overhead bei Nicht-Nutzung entfällt. [Eine gute Übersicht über Design Patterns finden Sie bei Stephan Schmidt, PHP Design Patterns, O’Reilly, Köln 2006. ]
Das Singleton-Entwurfsmuster
Beim Singleton-Entwurfsmuster handelt es sich um eine gängige Technik des objektorientierten Programmentwurfs, um eine einzige Instanz einer Klasse global verfügbar zu machen und die wiederholte Instanziierung der betreffenden Klasse zu verhindern. Sinnvoll ist dies zum Beispiel bei der Implementierung einer Datenbankverbindung oder für den Zugriff auf Applikationskonfigurationen. Eine für PHP 5 typische Implementierung für das Singleton-Entwurfsmuster sehen Sie im Beispielcode zum Lazy-Initialization-Konzept.
Ein gutes Beispiel für den Einsatz dieser Technik gibt die Database-Komponente, welche Klassen bereitstellt, um Datenbankverbindungen zu repräsentieren. Zwar werden die meisten Requests in einer typischen Webapplikation eine Datenbankverbindung benötigen, doch einige wenige werden diese nicht verwenden. Wenn beispielsweise Caching auf der Festplatte zum Einsatz kommt, ist die Datenbankverbindung im Fall von zwischengespeicherten Daten unnötig. Traditionell wird das entsprechende Verbindungsobjekt aber trotzdem erzeugt, da die Konfiguration, der Wartbarkeit halber, zentral am Anfang des Programms geschieht. Mit Lazy-Initialization lässt sich die Konfiguration des Objekts an zentraler Stelle vornehmen, ohne dass die entsprechende Objektinstanz dazu erzeugt werden muss. Dies spart im Falle der Nicht-Verwendung Platz im Arbeitsspeicher, Rechenzeit beim Kompilieren des benötigten Sourcecodes bei der Instanziierung großer Objekte und natürlich Zeit, die zum Aufbau der Datenbankverbindung verwendet würde. Des Weiteren wird die Datenbank entlastet, da unnötige Verbindungsanfragen vermieden werden. Neben der Database-Komponente unterstützen diesen Mechanismus unter anderem, die Komponenten Template, PersistentObject und Configuration. Wie Sie im Einzelnen bei jeder Komponente vorgehen müssen, um Lazy-Initialization zu verwenden, wird in dem Kapitel, das sich mit der entsprechenden Komponente beschäftigt, näher beleuchtet. Natürlich können Sie die von der Base-Komponente bereitgestellten Klassen für eigene Implementierungen von Lazy-Initialization verwenden, worauf wir an dieser Stelle kurz eingehen wollen. #### Konfigurierbare Klassen Um einer Klasse die Konfiguration mittels Lazy-Initialization zu ermöglichen, ist zunächst die Implementierung eines Singleton-Mechanismus nötig. Die hierbei erzeugte Instanz wird mittels Lazy-Initialization konfiguriert.
    class mySingletonClass
    {
        protected static $instance;
        protected function __construct() {}
        public static function getInstance()
        {
            if ( self::$instance === null )
            {
                self::$instance = new mySingletonClass();
                ezcBaseInit::fetchConfig(
                    'myIdentifier',
                    self::$instance
                );
            }
            return self::$instance;
        }
    }
Listing 2.9 Singleton-Instanzen per Lazy-Initialization konfigurieren Das Beispiel implementiert ein Singleton-Entwurfsmuster, wie es in PHP 5-Anwendungen häufig zu finden ist. Typisch sind hierbei der als protected markierte Konstruktor, um direkte Instanziierungen der Klasse zu verhindern, sowie das statische Attribut $instance und die dazu passende statische Methode getInstance(). Um an jeder Stelle der Applikation auf eine Instanz von myCustomSingleton zuzugreifen, muss diese Methode verwendet werden. Innerhalb der Methode wird überprüft, ob bereits eine Instanz der Klasse im $instance-Attribut existiert. Falls nicht, wird eine neue Instanz erzeugt. An dieser Stelle kommt nun die Lazy-Initialization zum Zuge und das frisch erzeugte Objekt wird hiermit konfiguriert. Die neu erstellte Instanz wird anschließend im dafür vorgesehenen Attribut gespeichert und somit beim nächsten Aufruf erneut verwendet. Zum Schluss wird das Objekt aus $instance zurückgegeben. Dem Aufruf von fetchConfig() auf der ezcBaseInit-Klasse wird ein eindeutiger Schlüssel übergeben, welcher den Lazy-Initialization-Mechanismus darüber informiert, wie die als zweiter Parameter übergebene Instanz zu konfigurieren ist. Ist der Klasse ezcBaseInit dieser Schlüssel nicht bekannt, unternimmt sie nichts und das Objekt wird nicht weiter konfiguriert, behält also seine Standardkonfiguration bei. Wie ein Schlüssel bekanntgemacht wird, sehen Sie in Kürze. #### Objektkonfigurationen Nun müssen Sie der Initialisierungsklasse lediglich mitteilen, wie beim Aufruf der fetchConfig()-Methode für einen bestimmten Schlüssel zu verfahren ist. Dazu wird zunächst eine weitere Klasse implementiert, die die Konfiguration des gewünschten Objekts auf Anfrage übernimmt:
    class mySingletonConfiguration implements
        ezcBaseConfigurationInitializer
    {
        public static function configureObject( $object )
        {
            echo "Configure mySingletonClass.\n";
            $object->option = 42;
        }
    }
Listing 2.10 Konfigurationsklasse für Lazy-Initialization Eine Klasse zur Realisierung der Konfiguration muss lediglich die statische Methode configureObject() implementieren. Dieser Methode wird die Instanz des zu konfigurierenden Objekts übergeben, woraufhin die Methode beliebig mit dem Objekt arbeiten kann. An dieser Stelle wird zum Beispiel der Wert des Attributs $value auf 42 gesetzt, was eine Konfiguration des Objekts andeuteten soll. Das Interface ezcBaseConfigurationInitualizer ist nicht verpflichtend, gibt Ihnen aber die Möglichkeit sicherzustellen, dass Ihnen kein Tippfehler beim Implementieren der benötigten Methode unterlaufen ist. Die Implementierungen der Klassen für Ihre eigene Lazy-Initialization können Sie zentral speichern, wie Sie es von Konfigurationen gewohnt sind, oder sie können aus der configureObject()-Methode ein entsprechendes Konfigurations-Backend anstoßen, wie es beispielsweise die Configuration-Komponente (siehe Kapitel 5, »Konfiguration«) bereitstellt. #### Lazy-Initialization einrichten Schließlich muss der ezcBaseInit-Klasse mitgeteilt werden, welche Klasse für die Konfiguration des Schlüssels myIdentifier zuständig ist. Diese Konfiguration muss in der Applikation immer vor dem ersten Zugriff auf das entsprechende Singleton passieren, damit der Effekt zum Tragen kommt:
    ezcBaseInit::setCallback(
        'myIdentifier',
        'mySingletonConfiguration'
    );
Listing 2.11 Konfigurationsklassen zuordnen Die Methode setCallback() erhält als ersten Parameter den betreffenden Schlüssel, als zweiten die dazu gehörende Konfigurationsklasse. Der Zugriff auf die fertig konfigurierte Instanz an beliebiger Stelle Ihrer Applikation funktioniert dann wie folgt:
    $object = mySingletonClass::getInstance();
    echo $object->option;
Listing 2.12 Auf Singleton-Instanzen zugreifen Der erste Aufruf in diesem Beispiel speichert die Singleton-Instanz in der Variablen $object. Ist dies das erste Mal, dass in Ihrer Applikation dieser Aufruf getätigt wird, so wird die neue Instanz von mySingletonClass erzeugt, per Lazy-Initialization konfiguriert, gespeichert und zurückgegeben. Beim nächsten Aufruf wird lediglich die bereits existierende Instanz verwendet. Der echo-Aufruf gibt also den gesetzten Wert 42 aus, falls dieser nicht vorher im Lauf der Applikation schon geändert wurde. ### Ihr Kommentar Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
<< zurück | <top> | vor >>
Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen? Ihre Meinung
Buchempfehlungen
| PHP 5.3 und MySQL 5.1
| Besser PHP programmieren
| Webshops mit Magento
| Sichere Webanwendungen
| PHP 5.3 und MySQL 5.1 - Videotraining
| Apache 2
| Suchmaschinen- Optimierung für Webentwickler
| Joomla! 1.5
Shopping
Versandkostenfrei bestellen in Deutschland und Österreich Info

Copyright © Galileo Press 2008
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

[Galileo Computing]
Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de