# Praktische Einführung: Vorwort

Websiteentwicklung PHP Praktische Einführung Vorwort

## Konzept

* Zielgruppe: Anfänger in der PHP-Programmierung. Kenntnisse von einfachem XHTML (Abschnitt Grundlagen), später auch SQL (Grundlagen und JOIN) werden vorausgesetzt.
* Lernziele: Nach den praxisorientierten Kapiteln sollen grundlegende PHP-Kenntnisse vorhanden sein. Der Leser muss nicht jeden Aspekt der Sprache kennen, sondern sollte die am häufigsten gebrauchten Elemente verständig anwenden können. Er weiß, wie er sich selbstständig weiterführende Informationen beschaffen und auf häufig auftretende Fehlermeldungen reagieren kann, verwendet Best Practices, kennt mögliche Angriffsvektoren und trifft entsprechend Vorsorge.
* Buchpatenschaft/Ansprechperson: Zur Zeit niemand. Buch darf übernommen werden.
* Sind Co-Autoren gegenwärtig erwünscht? Wiki-Prinzip: Alle können sich beteiligen.
* Richtlinien für Co-Autoren:
** Anrede: Du
** Rechtschreibung: Neu
** Coding-Standard: PEAR (zweifache statt vierfache Einrückung)
** Nicht-PHP-Elemente (XHTML, Design, Bilder, Beispieldaten) des Beispielprojektes werden zum Download angeboten, da hier nicht HTML erlernt werden soll
* Projektumfang und Abgrenzung zu anderen Wikibooks: Aufgrund fehlender Anfängerfreundlichkeit (siehe Diskussionsseite) des bestehenden Buches ist dies ein einführender Abschnitt zu Websiteentwicklung: PHP im Tutorial-Stil, inspiriert durch das (verwaiste) Buch PHP praxisorientiert lernen. Die bereits vorhandenen Kapitel werden zu Referenzkapiteln, die auch auf nicht im Tutorial erwähnte Dinge eingehen (z.B. HEREDOC/NOWDOC).
* Themenbeschreibung: Grundlagen der PHP-Programmierung, erklärt anhand eines Beispielprojekts (dynamische Website mit Benutzerinteraktion).
* Aufbau des (Teil)buches: Die Kapitel führen in das jeweilige Thema ein und zeigen, falls möglich, Anwendungsfälle für das Beispielprojekt. Wird auf ein Thema nicht vollständig eingegangen, führen Links zu den ausführlichen, bereits vorhandenen Kapiteln dieses Buches. Übungen ergänzen die Kapitel und überprüfen das Verständnis des Lesers.

## Vorwort für die Autoren
### Warum alles zweimal?

Die bereits bestehenden Kapitel bieten eine umfangreiche Referenz zu PHP. Die Fülle an Informationen ist allerdings für einen Anfänger eher abschreckend als hilfreich, es kommt beim Lesen kein "Lernfluss" auf. Gutes Beispiel dafür sind die Websiteentwicklung: PHP: Operatoren: Der Zweck von Vergleichsoperatoren erschließt sich dem Leser erst nach Kenntnis über Kontrollstrukturen – die erwirbt er jedoch erst im folgenden Kapitel.
Die bisher bestehenden Kapitel werden durch die Einführung nicht überflüssig, sondern sind als vollständiges Kompendium weiterhin notwendig.

### Warum so wenig Praxis?

Obwohl die Überschrift "Praktische Einführung" lautet, wird der Leser erst spät echte Anwendungen kennen lernen. Das liegt zum einen daran, dass die Kenntnisse aufeinander aufbauen: Bevor der Leser mit dem superglobalen Arrays arbeiten kann, muss er die Bedeutung von Arrays kennen, und dafür wiederum Variablen. Viele Tutorials zeigen zunächst mit Beispielen, was PHP kann, und erklären erst viel später die Syntax. Der Leser wird vermutlich schon früh experimentieren, ohne zu wissen, was es mit den Zeichen für eine Bewandtnis hat. Das führt zum zweiten Grund, warum die Praxis erst fast am Ende Einzug findet: Sicherheit. Wie in den verschiedenen Foren zu PHP ersichtlich wird, ist ein häufiger Fehler fehlende oder mangelhafte Kenntnisse über Sicherheitslücken. Daher soll der Leser nicht erfahren, wie man Benutzereingaben verarbeitet, bis er über die Sicherheitsrisiken Bescheid weiß.

## Vorwort für den Leser

Diese Einführung soll dir die Grundlagen der Programmiersprache PHP näher bringen. Dabei wird Wert darauf gelegt, dass du nicht nur praktische Anwendungsbeispiele kennen, sondern auch sichere und effektive Skripte schreiben lernst.
Der praktisch orientierte Ansatz bringt es allerdings mit sich, dass nicht auf alle Details eingegangen werden kann. Ist dies der Fall, findest du in den Abschnitten jeweils Links zu umfassenderen Informationen eines Themas. Du kannst diese Abschnitte überspringen und später nachlesen.
* Hinweis
* Einige der verwendeten Fachbegriffe kannst du im Glossar nachschlagen. Dort findest du auch Verweise zu den Kapiteln, in denen der Begriff zum ersten Mal auftaucht.

## Benötigte Vorkenntnisse

Um mit diesem Buch arbeiten zu können, benötigst du allgemeine Kenntnisse im Umgang mit dem Computer. Da das Beispielprojekt eine Website zum Thema hat, wird außerdem die Beherrschung von (X)HTML vorausgesetzt. Später kommt eine relationale Datenbank hinzu, die über die Sprache SQL abgefragt wird. Allgemeine Kenntnisse über Strukturen von Programmiersprachen sind zwar hilfreich, aber nicht zwingend erforderlich; es werden alle Begriffe ausführlich eingeführt.

## Das Beispielprojekt

Nach der Einführung in die Grundelemente der Sprache wirst du eine interaktive Website erstellen. Diese fiktive Seite stellt jeden Monat ein Wikibook vor.
Die Website, bisher statisch, soll um folgende Funktionen ergänzt werden:
* Templates, um das Layout vom Inhalt und beide vom Programmcode zu trennen
* einen Front-Controller (Alle Unterseiten werden von einer index.php aufgerufen)
* eine relationale Datenbank, um die Artikel dort zu speichern
* Benutzerauthentifizierung
* Kommentare unter den Artikeln
* Vorschläge für neue Buchvorstellungen einreichen

## Was ist PHP?

PHP (Backronym für PHP: Hypertext Preprocessor) ist eine Programmiersprache, die 1995 von Rasmus Lerdorf unter dem damaligen Namen PHP/FI begründet wurde. Sie war von Beginn an für den Einsatz auf Webservern vorgesehen, inzwischen kann PHP jedoch für fast jede Programmieraufgabe herangezogen werden, sogar für Desktopapplikationen (mit der Erweiterung PHP-GTK). Es handelt sich um eine Skriptsprache, was bedeutet, dass alle PHP-Programme bei jeder Ausführung durch einen Interpreter geschickt werden, der die Befehle parst (in interne Symbole übersetzt) und dann zur Laufzeit interpretiert. Ein PHP-Programm besteht aus Anweisungen, die Schritt für Schritt abgearbeitet werden. Sobald alle Anweisungen ausgeführt worden sind, wird das Skript bzw. Programm beendet. Im Gegensatz zu anderen Sprachen dauern die Skripte daher normalerweise nur wenige Sekunden.

## PHP ist nicht Javascript

PHP ist eine serverseitige Programmiersprache. Die Befehle werden auf einem Webserver ausgeführt und die Ausgabe an den Browser des Benutzers zurückgesendet. Im Gegensatz zu Javascript kann der Benutzer nicht den Code deines Skriptes einsehen (außer, der Server ist fehlerhaft konfiguriert). Gleichzeitig kannst du so Inhalte vor Benutzern verstecken, die diese nicht sehen sollen, etwa eine Administrationsoberfläche.
Ruft der Benutzer ein PHP-Skript auf, wird jedoch die komplette Seite neu geladen. Das zeigt einen weiteren Unterschied zu Javascript. Nur mit letzterer Sprache kann man z.B. Tabellen ohne Neuladen aufklappen oder beim Tippen ein Eingabefeld rot färben, weil die Eingabe ungültig ist (was einen Benutzer nicht daran hindern kann, dennoch ungültige Eingaben zu senden; siehe dazu das Kapitel Benutzereingaben und Sicherheit).
Wenn du beide Sprachen kombinieren möchtest, solltest du einen Blick in das Wikibook AJAX werfen.

# Praktische Einführung: PHP einrichten

Websiteentwicklung PHP Praktische Einführung PHP einrichten

## Wie PHP funktioniert

Obwohl du mit PHP jede beliebige Anwendung programmieren kannst (mit PHP-GTK sogar eine graphische Benutzeroberfläche), wird es vor allem für dynamische Webseiten verwendet. Wenn du eine PHP-Seite im Internet aufrufst, geschieht folgendes:
* Der Webserver ist für HTTP-Anfragen verschiedener Benutzer zuständig. Im Beispiel des Schaubilds fragt der Browser des Zugreifenden nach der Datei "beispiel.php". Sollte der Webserver diese nicht im Webverzeichnis (z.B. /var/www/) finden, wird er eine Fehlerseite ausgeben.
* Wenn er die Datei findet, wird der Server sie je nach Typ unterschiedlich behandeln. Normalerweise ist er so eingerichtet, dass Dateien mit der Endung ".html" sofort an den Benutzer geschickt werden, während er ".php"-Dateien zunächst an ein weiteres Programm, den PHP-Interpreter, übergibt. Dieser führt die in der Datei vorhandenen PHP-Befehle Schritt für Schritt aus.
* Die Ausgabe des Interpreters sendet der Webserver anschließend an den Benutzer.

## Was du benötigst

Für diese Einführung in PHP benötigst du:
* PHP-Interpreter (Version 5.1 oder höher)
* Einen Webserver (z.B. Apache)
* Eine relationale Datenbank (z.B. MySQL)
Außerdem hilfreich: Ein Editor oder eine IDE mit Syntaxhighlighting. Wikipedia hat dazu eine Liste von Texteditoren und eine Liste von Integrierten Entwicklungsumgebungen.
Es gibt mehrere Möglichkeiten, wie du an diese Komponenten gelangst:

## Verfügbaren Webspace nutzen

Wenn du über einen Webspace oder einen Server verfügst, ist es sehr wahrscheinlich, dass dort bereits PHP installiert ist. Um herauszufinden, um welche Version es sich handelt, kannst du eine Datei "index.php" mit dem Inhalt
hochladen und mit deinem Browser aufrufen.
Diese Methode hat den Vorteil, dass du absolut nichts installieren brauchst. Allerdings musst du deine Skripte bei einer Änderung hochladen, um dir das neue Ergebnis anzuzeigen. Zudem hast du, wenn es sich um einen Shared-Server handelt, kaum bis gar keine Kontrolle über die Konfiguration in der php.ini (der Konfigurationsdatei von PHP). Darin könnten unsichere (register_globals = on) oder für das Lernen hinderliche (display_errors = 0) Einstellungen aktiv sein.
Ein weiterer Nachteil ist das Sicherheitsrisiko. Da auf die Skripte von überall zugegriffen werden kann, solltest du nicht die Beispiele ausprobieren, die mit "unsicher" gekennzeichnet sind.

## XAMPP installieren

XAMPP steht für Apache, MySQL, Perl und PHP und ist ein fertig konfiguriertes Paket mit diesen (und einigen weiteren) Komponenten für Windows, Mac OS X, Linux und Solaris. XAMPP kannst du unter der Adresse http://www.apachefriends.org/de/xampp.html herunterladen. Nach der Installation startest du den Webserver Apache über das XAMPP Control Panel; genauso auch MySQL, sobald du es benötigst. Deine Skripte speicherst du dazu im Ordner htdocs im xampp-Verzeichnis. Wenn der Server läuft, erreichst du diese über http://localhost/. Hast du also z.B. eine Datei "test.php" in das Verzeichnis xampp/htdocs/tutorial/ abgelegt, kannst du dieses Skript über http://localhost/tutorial/test.php aufrufen.
Linux bringt in der Regel einen Webserver mit sich. Eine Anleitung, wie du diesen für die Verwendung von PHP einrichtest, findest du in der Hilfe deiner Distribution (z.B. für Ubuntu). Alternativ kannst du XAMPP für Linux (ehemals LAMPP) herunterladen und installieren.

## Selbst kompilieren

Wenn du ein erfahrener Anwender bist und den Aufwand, den eine Serverkonfiguration mit sich bringt, nicht scheust, kannst du den neuesten Quellcode von der PHP-Website herunterladen und kompilieren. Anschließend musst du noch einen Webserver und eine Datenbank deiner Wahl installieren.

# Praktische Einführung: Erste Schritte

Websiteentwicklung PHP Praktische Einführung Erste Schritte
Dies wäre keine Einführung in eine Programmiersprache ohne ein Hallo-Welt-Programm. Öffne einen Texteditor deiner Wahl, der, wie bereits erwähnt, Syntax-Highlighting anbieten sollte, und gib den folgenden Code ein:
Die Zeichen um Hallo Welt werden einfache Anführungszeichen genannt (obwohl sie technisch eigentlich ein Sekundenzeichen sind) und befinden sich normalerweise auf der Raute-Taste.
Speichere dieses Skript nun im Ordner "tutorial/index.php" im Document-Root deines Webservers ab ("htdocs" in XAMPP/LAMPP) und rufe es auf.
Als Ausgabe erhältst du:
* Hinweis
* Wenn dir statt der Ausgabe angeboten wird, die Datei "index.php" herunterzuladen, ist etwas bei der Konfiguration des Webservers schief gelaufen. Verwendest du XAMPP/LAMMP, überprüfe, ob der Apache gestartet ist und du die Datei über http://localhost aufrufst.
Dieselbe Ausgabe hättest du auch mit HTML allein erreichen können. Tatsächlich kommt beim Benutzer nur HTML-Code an, denn PHP-Code wird auf dem Server ausgeführt und nur die Ausgabe an den Browser gesendet.

## PHP-Tags

Alle PHP-Anweisungen müssen in PHP-Tags stehen. Der Anweisungsbereich beginnt mit <?php und endet mit ?>. Alles, was sich außerhalb von PHP-Tags befindet, wird vom Interpreter direkt ausgegeben und ansonsten ignoriert. Das kann HTML, XML usw. sein. Innerhalb der PHP-Tags darf nur gültiger PHP-Code stehen. In einem PHP-Dokument kann es beliebig viele PHP-Tags geben. Das ist also problemlos möglich:

## Kommentare

Bevor wir ins Detail gehen, ein Wort zu Kommentaren: Diese sind, wie der Name schon sagt, Anmerkungen, die vom Interpreter komplett ignoriert werden. Es gibt zwei Arten von Kommentaren: Einzeilige Kommentare (begonnen mit //), die nur bis zum Ende einer Zeile gehen, und mehrzeilige Kommentare (umschlossen von /* und */).
Kommentare mögen zunächst nutzlos scheinen, da sie ignoriert werden; für den Programmieralltag sind sie jedoch unerlässlich. Du solltest alle deine selbst geschriebenen Funktionen, Klassen, Methoden usw. mit Kommentaren versehen, um auch später noch nachvollziehen zu können, welchen Zweck sie erfüllen. Auch Anweisungen selbst können Kommentare vertragen. Als Faustregel gilt allerdings: Guter Code spricht für sich selbst. Du kannst dir bestimmt denken, was der Befehl $page->setTitle('Startseite') bewirkt, obwohl du nicht weißt, was die einzelnen Zeichen dazwischen für eine Wirkung haben. Im Gegensatz dazu ist special_function($var23, $var5) schlechter Code, denn du wirst bald schon wieder vergessen haben, was an der Funktion so "special" war.
Innerhalb dieses Buches werden Kommentare verwendet, um Hinweise zum Ergebnis und Zweck von Anweisungen zu geben.

## Der Code im Detail

Sehen wir uns den Code einmal genau an:

### Anweisungen

Eine Anweisung in PHP endet mit einem Semikolon (;). echo 'Hallo Welt'; ist somit eine Anweisung, während
zwei Anweisungen sind. Anweisungen werden ausgeführt. Sie müssen dabei noch nicht einmal etwas Sinnvolles tun. Die Anweisung
wird gar keinen Effekt haben. Anweisungen bestehen aus Ausdrücken. Ausdrücke sind z.B. eine Zuweisung, eine Variable oder ein Funktionsaufruf. Selbst der konstante Wert 'Hallo Welt' ist ein Ausdruck. Es macht nichts, wenn du mit diesen Begriffen noch nichts anfangen kannst, da sie dir in den späteren Kapiteln näher gebracht werden.

### Funktionsaufruf

Eine Funktion ist ein Bündel von einer oder mehreren Anweisungen, das mit dem Aufruf der Funktion ausgeführt wird. Du kannst dir eine Funktion wie ein kleineres Programm vorstellen, welches dir die Arbeit erleichtert. Wie (und warum) du eigene Funktionen deklarierst, erfährst du im Kapitel Eigene Funktionen. Für den Augenblick genügt uns der Aufruf einer Funktion.
Eine Funktion rufst du über ihren Namen, gefolgt von Klammern auf. Hast du also beispielsweise eine Funktion "do_login" geschrieben, kannst du sie mittels do_login aufrufen. In Funktionsnamen sind keine Leerzeichen erlaubt. Es ist üblich statt eines Leerzeichens einen Unterstrich "_" zu benutzen.
Eine Funktion kann Argumente (auch Parameter genannt) haben. Mit Argumenten gibst du der Funktion etwas "in die Hand". Ohne Argumente müsste man für jede kleinste Abweichung der Funktionsanweisungen eine eigene Funktion erstellen.
Argumente werden in PHP innerhalb der Klammern übergeben. Gibt es mehrere Argumente, werden sie durch Kommas getrennt. Angenommen, deine Funktion "do_login" benötigt zwei Argumente, einen Benutzernamen und ein Passwort, so wären folgende Funktionsaufrufe alle gültig:
Weitere Informationen über Argumente erhältst du später in dieser Einführung.
Auch echo ist in gewisser Weise eine Funktion, obwohl es von keinen Klammern gefolgt wird. Das liegt daran, dass es sich bei echo um ein Sprachkonstrukt handelt. Was das bedeutet, brauchst du im Moment nicht zu wissen. Es reicht, wenn dir bewusst ist, dass echo im Grunde wie eine Funktion funktioniert und keine Klammern benötigt.
Das Resultat einer Funktion kann übrigens Argument einer anderen Funktion sein, die wiederum das Argument einer Funktion ist. Hier ein Beispiel:
Wie in der Mathematik auch, wird der Code von der innersten bis zur äußersten Klammer ausgewertet. Die innerste Funktion substr schneidet einen Teil aus einer Zeichenkette aus und gibt diesen zurück. Sie nimmt maximal drei Argumente entgegen: Als erstes die Zeichenkette selbst, dann ab wo begonnen werden soll (0) und anschließend die Zahl der Zeichen, die vom Start ab entnommen werden sollen (5). Dieser Aufruf wird "Hallo" zurückgeben, da dies die ersten fünf Zeichen der Zeichenkette "Hallo Welt!" sind. Anschließend wird dieses "Hallo" als Argument an die Funktion strlen übergeben. Diese hat nur ein einziges Argument: Eine Zeichenkette. Zurückgegeben wird deren Länge (5). Zum Schluss geht diese 5 an die "Funktion" echo, die, wie du bereits weißt, alle ihre Argumente ausgibt.

# Praktische Einführung: Variablen

Websiteentwicklung PHP Praktische Einführung Variablen
Nun weißt du zwar bereits, was Anweisungen in PHP sind und wie du Funktionen ausführst, bisher konntest du allerdings noch nichts hilfreiches machen. Das wollen wir jetzt ändern: Wir wollen dem Besucher den aktuellen Wochentag, sowie den Wochentag in einem Jahr anzeigen.
Dabei halten wir uns an das EVA-Prinzip und versuchen, den verarbeitenden Code von der Ausgabe zu trennen. Zunächst das Ausgangsskript:
setlocale sorgt dafür, dass die richtige Sprache für die Anzeige des Wochentages verwendet wird. Das erste Argument gibt an, für welchen Bereich (z.B. Währungs- oder Zeitfunktionen) die Region gesetzt werden soll. Wir haben dafür eine Konstante verwendet - dazu später mehr. Die restlichen Argumente sind verschiedene Möglichkeiten, "deutsch" als gewünschte Sprache einzustellen. Wenn die erste Schreibweise dem System nicht bekannt ist, wird die zweite probiert, usw.
strftime gibt eine formatierte Zeichenkette zurück. Das erste Argument ist das gewünschte Format ("%A" steht für "Wochentag, ausgeschrieben"), das zweite ein Timestamp. Da dieser optional ist, haben wir ihn weggelassen. Es wird dann automatisch die aktuelle Zeit des Servers verwendet. Weitere Formate findest du in der Dokumentation von strftime im PHP-Handbuch.
strtotime wandelt eine Zeichenkette wieder in einen Timestamp um. Mit strtotime sind auch relative Angaben möglich, wie "yesterday 14:00", "4 months 6 days ago" oder, wie hier verwendet, "+1 year". Diesen Timestamp übergeben wir dann wiederum der Funktion strftime, die uns den Wochentag dieses Zeitpunktes zurück gibt.
Wir können den unteren Teil jedoch noch übersichtlicher gestalten, indem wir die Ergebnisse der beiden strftime-Aufrufe in Variablen speichern.

## Was sind Variablen?

Variablen sind wie Behälter. Sie speichern einen Wert ab, und man kann diesen Wert anschließend an Funktionen weiterreichen oder Operatoren verwenden. Variablen sind unerlässlich, wenn du das Ergebnis von Funktionen zur späteren Verwendung im Skript festhalten willst.
Variablen beginnen in PHP immer mit dem Dollarzeichen ($), gefolgt vom Namen der Variable. Der Name darf nur Buchstaben, Ziffern und Unterstriche enthalten; das erste Zeichen darf dabei keine Zahl sein.
* Hinweis
* Anders als in anderen Programmiersprachen muss man in PHP eine Variable vor der Verwendung nicht definieren. Allerdings wird PHP auf der höchsten error_reporting-Stufe einen Hinweis ausgeben, wenn man versucht, eine nicht vorhandene Variable an eine Funktion oder Kontrollstruktur zu übergeben.

## Variablen zuweisen

Du kannst einer Variable einen Wert mit dem Zuweisungsoperator = (einfaches Gleichheitszeichen) zuweisen. Dabei wird stets der linken Variable der rechte Wert zugewiesen:
PHP beachtet bei Variablen die Groß- und Kleinschreibung: $test bezeichnet eine andere Variable als $TEST. Es ist eine gängige Konvention, Variablennamen immer klein zu schreiben.
Wenn einer Variable der Wert einer anderen Variable zugewiesen wird, so erhält diese eine Kopie des Wertes. Die beiden Variablen bleiben unabhängig voneinander. Deshalb ist es wichtig, dass du dich von der Vorstellung des = als Gleichheitszeichen löst. In PHP bedeutet es schlicht: "Weise der Variable links von mir den Wert rechts von mir zu". Es gibt allerdings eine Möglichkeit, Variablen als beständigen Verweis auf eine andere Variable zu verwenden (sog. Referenzen). Referenzen können, richtig angewendet, Problemstellungen vereinfachen, sind zu Beginn jedoch nicht leicht zu verstehen. Mehr dazu findest du im Kapitel Referenzen.

## HTTP ist zustandslos

Wie eingangs erwähnt, haben PHP-Skripte in der Web-Welt meist nur eine Lebensdauer von einigen wenigen Sekunden. Sobald ein Skript beendet wurde, sind die Variablen weg. Folgendes Skript wird niemals etwas ausgeben, egal, wie oft du es aufrufst:
Solltest du einmal etwas für eine längere Dauer speichern wollen, könntest du den Wert in eine Datenbank schreiben, eine Datei erstellen, im Arbeitsspeicher oder in der Benutzersitzung ablegen.

## Anwendung

Wenden wir nun das Gelernte an:
Ohne es zu wissen, hast du damit bereits eine wichtige Technik angewendet: Das Templating, welches dir im nächsten Kapitel vorgestellt wird.

## Konstanten

Es gibt noch besondere "Container" für Werte: Die Konstanten. Vielleicht sind dir Konstanten bereits aus der Mathematik bekannt (Pi oder die Eulersche Zahl). Wie der Name bereits verrät, sind diese, einmal festgelegt, unabänderlich. Sie werden mit der Funktion define definiert:
* Hinweis
* Da PHP bei Konstanten in der Regel ebenso auf die Groß- und Kleinschreibung achtet, ist es eine Konvention, alle Konstanten groß zu schreiben.
Konstanten können nur einfache Werte enthalten (boolean, string, integer, float), also keine Arrays oder Objekte. Was das genau bedeutet, wirst du später in dieser Einführung (im Kapitel Typen und Operatoren) erfahren.
Ihren Wert rufst du ab, indem du einfach ihren Namen schreibst (ohne $!):
Sinnvoll sind Konstanten vor allem als Argumente von Funktionen. Die Funktion trigger_error, die es dir ermöglicht, einen PHP-Fehler zu erzeugen, erwartet als zweites, optionales Argument den Typ des Fehlers:
Ausgabe (ähnlich):
Hinter den Konstanten verbergen sich Zahlen. E_USER_NOTICE hat z.B. den Wert 1024, du hättest also auch einfach 1024 schreiben können. Dagegen sprechen zwei Dinge:
* Konstanten haben einen Namen. Du musst dir nicht merken, dass du für einen Hinweis die Zahl 1024 brauchst.
* Bei einer Änderung des Werts muss das Script nur an einer einzigen Stelle geändert werden. Die PHP-Entwickler könnten eines Tages zu der Auffassung gelangen, dass 32768 viel besser für E_USER_NOTICE ist.

# Praktische Einführung: Templating

Websiteentwicklung PHP Praktische Einführung Templating

## Warum Templating?

In den Anfängen war PHP zwar bereits sehr mächtig, aber noch lange keine komplexe Programmiersprache. Mit der Zeit wurden die Befehle und die Syntax komplexer, die Programmteile länger und die mit PHP gefüllten HTML-Tags schwerer zu verstehen. Ohne die Bedeutung der Befehle zu kennen, wirst du auf einen Blick sehen, dass
um einiges unübersichtlicher ist als
Das letzte Codebeispiel zeigt ein Template.
Templates (engl. für "Vorlagen") sind keine Eigenheit von PHP, sondern ein Programmiergrundsatz. Sie finden nicht nur, aber besonders in der Webprogrammierung Anwendung. Mit Hilfe von Templates kannst du Geschäftslogik von Darstellungslogik trennen.
Beispiele für Geschäftslogik:
* Verbindung zu einer Datenbank und Abruf von Daten
* Speichern von Dateien
* Berechnungen
* Verarbeitung von Formularen
Beispiele für Darstellungslogik:
* Tabellenzeilen abwechselnd farbig gestalten
* Formular anzeigen
* Variablen ausgeben

## Der Befehl "include"

Um in PHP anderen PHP-Code einzubinden, kannst du den include-Befehl verwenden:
Obwohl es bei einem include egal ist, welche Endung die Datei hat (sie wird immer interpretiert), solltest du sie mit der Endung ".php" abspeichern. Ansonsten könnte jeder, bei sonst fehlender Absicherung, den Quelltext deiner eingebundenen Dateien lesen.
Sobald PHP eine include-Anweisung ausführt, sucht er nach dieser Datei, führt den darin enthaltenen Code aus und kehrt dann wieder in das Ursprungsscript zurück. Du kannst einen relativen oder einen absoluten Pfad angeben. Bei einem relativen Pfad sucht PHP zunächst relativ zum Skript, das die Include-Anweisung enthält, aufruft, anschließend relativ zum äußeren Skript usw., zum Schluss im include_path, der in der php.ini festgelegt werden kann.
Es gibt noch drei weitere Anweisungen zum Einbinden von Dateien. Diese findest du im Referenzkapitel Quellcode wiederverwenden.

## Anwendung

Um das Beispiel für Templating vorzubereiten, werden folgende Dateien benötigt:
* eine "index.php", in der sich die Geschäftslogik befindet
* die beiden Templates "header.tpl.php" und "footer.tpl.php", die wir der Übersichtlichkeit halber in einen Unterordner "templates" packen
* ein drittes Template "day.tpl.php", ebenfalls im Ordner "templates"
Die Endung auf "tpl.php" ist willkürlich gewählt. Genauso gut können die Dateien auch auf "template" oder "birne" enden.
In der index.php befindet sich folgender Code:
In der header.tpl.php:
In der footer.tpl.php:
Und schließlich in der day.tpl.php:

# Praktische Einführung: Typen und Operatoren

Websiteentwicklung PHP Praktische Einführung Typen und Operatoren
In den vorigen Kapiteln hast du Zahlen einfach eingegeben, während Text in einfache Anführungszeichen gesetzt wurde. Zahlen und Text sind zwei verschiedene Dinge, man kann auch sagen: Typen. PHP ist eine schwach typisierte Sprache, das heißt, Variablen wechseln je nach Bedarf ihre Typen, aus Ganzzahlen werden Zeichenketten und umgekehrt. In diesem Kapitel werden dir die vier skalaren Typen vorgestellt sowie die Operatoren.

## var_dump

Wann immer du dir Informationen über eine Variable anzeigen lassen möchtest, kannst du die Funktion var_dump verwenden. Sie gibt dir Informationen über Typ und Inhalt dieser Variable:

## String

Der erste Typ, den du kennen gelernt hast, war der String. Ein String kann Zeichen enthalten:

### Strings definieren

Es gibt vier Wege, in PHP einen String innerhalb des Codes (also nicht beispielsweise durch Auslesen einer Datei) zu definieren, von denen dir hier die zwei wichtigsten vorgestellt werden.

#### Einfache Anführungszeichen

Diese Methode hast du bisher verwendet. Du brauchst hierbei nichts zu beachten, außer, du willst das einfache Anführungszeichen selbst ausgeben. Dann musst du es mit einem Backslash (\) escapen:
Da der Backslash als Escapezeichen verwendet wird, musst du, wenn du diesen ausgeben willst, den Backslash selbst escapen (\\).

#### Doppelte Anführungszeichen

Ein String in doppelten Anführungszeichen wird um besondere Funktionen erweitert: Zum einen werden spezielle Escapezeichen erkannt (etwa \n für eine neue Zeile), zum anderen werden Variablen im String erkannt. Beispiele:
Es kann vorkommen, dass auf den Variablennamen noch ein Zeichen folgen kann, was PHP dem Variablennamen zurechnen würde:
PHP wird im String die Variable $variablen lesen. Da die Variable nicht definiert wurde, wird sie durch nichts ersetzt.
Um PHP zu sagen, dass er die Variable "$variable" nehmen soll und das n lediglich für den Plural dort steht, kannst du die Schreibweise mit geschweiften Klammern verwenden:
* Hinweis
* Auf der höchsten error_reporting-Stufe hätte PHP einen Hinweis ausgegeben, dass eine nicht definierte Variable verwendet wurde. Bei der Fehlersuche ist diese höchste Stufe sehr hilfreich. Du findest mehr Informationen dazu im Kapitel Fehlerbehandlung.

### Der Verkettungsoperator (.)

Um aus zwei Strings einen zu machen, kannst du den Verkettungsoperator (.) verwenden:
Für die Zuweisung $variable = $variable . $string gibt es auch eine Kurzschreibweise:

## Integer

Ein Integer ist eine Ganzzahl (mathematisch ausgedrückt: Ein Element aus der Menge Z).

### Die Operatoren +, -, *, / und %

Auf Integers kannst du die üblichen Rechenoperationen anwenden: + Addition, - Subtraktion, * Multiplikation und / Division, sowie den Modulus %, der den Rest einer Division zurückgibt.
Auch für diese Operatoren gibt es Kurzschreibweisen (+=, -=, *=, /= und %=).
^ ist übrigens kein Zeichen für Potenzen, wie es in manchen Sprachen üblich ist, sondern ein Bitoperator. Bitoperatoren werden nur in sehr seltenen Fällen benötigt. Mehr Informationen findest du im entsprechenden Referenzkapitel Operatoren. Verwende für die Potenzoperation die Funktion pow.

### Inkrement- und Dekrementoperator

Eine Besonderheit sind der Inkrement- und der Dekrementoperator. Häufig muss man den Wert einer Variable um exakt eins erhöhen oder erniedrigen. Anstatt nun $i += 1 schreiben zu müssen, gibt es eine noch kürzere Schreibweise: $i++. Es ist üblich, diese Operatoren im Zusammenhang mit Schleifen zu verwenden.
Zwischen den beiden Varianten mit $i++ bzw. $i-- auf der einen, ++$i und --$i auf der anderen Seite gibt es nur einen kleinen Unterschied: Wenn der Operator vor der Variable steht, wird zunächst die Variable um eins erhöht/erniedrigt und dann zurückgegeben; steht der Operator nach der Variable, wird erst der alte Wert zurückgegeben und dann die Variable um eins erhöht.

## Float

Variablen vom Typ Float sind Fließkommazahlen, oder, mathematisch ausgedrückt, Dezimalzahlen. Beachte, dass die englische Notation verwendet wird, in der ein Komma ein Punkt ist (also z.B. 12.4 für 12,4). Das Komma wird in PHP ausschließlich zur Trennung von Argumenten verwendet, der Punkt sowohl zur Verkettung von Strings als auch als Dezimalzeichen.
Auf Floats können die gleichen Rechenoperationen wie auf Integers angewendet werden.

## Boolean

Eine Variable vom Typ Boolean kann nur zwei Werte annehmen: 1 oder 0, an oder aus, wahr (true) oder falsch (false). Booleans werden am häufigsten in Kontrollstrukturen benutzt und von vielen Funktionen zurückgegeben. Einen Boolean definierst du über die (speziellen) Konstanten true oder false.

## Casting

Wenn du einen Integer mit echo ausgibst, wird dieser automatisch in einen String umgewandelt, da echo nur Strings als Argumente erwartet. Wenn du zwei Strings addierst, etwa '5' und '15', werden diese in Integers konvertiert. Wenn du zehn durch drei teilst, ist das Ergebnis vom Typ Float.
PHP ist, wie schon erwähnt, eine schwach typisierte Sprache und lässt solche Dinge zu. Manchmal kann es aber nötig sein, eine Variable explizit auf einen bestimmten Typ zu setzen. Dies geschieht mittels Casting: Schreibe einfach vor die Variable den Namen des Typs in Klammern.
Umfangreiche Informationen, was bei einem Casting für ein Wert angenommen wird, findest du im Referenzkapitel Variablen.

### Spezialfall Booleans

Wenn man eine Variable zu einem Boolean castet (was implizit in einigen Kontrollstrukturen, welche wir später noch kennenlernen, passiert), ist es wichtig zu wissen, welche Werte true und welche Werte false ergeben, da dies in PHP nicht so einfach ist wie in manchen anderen Sprachen.
Alle folgenden Werte werden dabei als false ausgewertet:
Alle anderen Werte werden als true ausgewertet!

# Praktische Einführung: Mit dem PHP-Handbuch arbeiten

Websiteentwicklung PHP Praktische Einführung Mit dem PHP-Handbuch arbeiten
Dieses Buch kann dir nicht jede Funktion vorstellen, die es in PHP gibt (das ist auch gar nicht seine Aufgabe). Wenn du Informationen brauchst, warum dieser oder jener Fehler auftritt, oder was das fünfte Argument einer sehr komplizierten Funktion bewirkt, kannst du im PHP-Handbuch nachschlagen. Du findest es unter http://de.php.net/docs.php.

## Eine Funktion für einen bestimmten Zweck finden

Wenn man nicht genau weiß, wie die Funktion heißt, die man sucht, kann man durch die Funktionsreferenz blättern. Sucht man beispielsweise eine Funktion, um herauszufinden, ob ein String in einem String enthalten ist, sollte man selbstverständlich bei den String-Funktionen nachschlagen. Dort findet sich eine Liste mit allen Stringfunktionen und einer Beschreibung in einem kurzen Satz. Bei strpos werden wir schließlich fündig.
Solltest du bereits wissen, wie eine Funktion heißt, möchtest jedoch die Erklärung dazu aufrufen, kannst du dies mit der PHP-Referenz direkt über die URL tun:

## Die Funktionsbeschreibung

Jede Funktion hat im PHP-Handbuch eine ähnlich aussehende Funktionsbeschreibung. Oben finden sich Angaben zu den Versionen, in denen die Funktion vorhanden ist (z.B. "(PHP 4, PHP 5)"), darunter die Ein-Satz-Beschreibung und die Funktionssignatur. Die Signatur für strpos lautet beispielsweise:
Dadurch erfährst du, dass die Funktion ein Integer zurückgibt und drei Argumente hat. Das erste Argument muss ein String sein (oder wird automatisch dazu gecastet), das zweite darf von einem beliebigem Typ sein ("mixed" gibt es nicht wirklich als Typ, er wird nur innerhalb der Dokumentation verwendet). Der letzte Parameter ist in eckige Klammern gesetzt, was darauf hinweist, dass dieser optional ist. Die Benennung der Argumente ist nur für die Dokumentation, diese helfen aber in der Regel beim Verständnis. So wird mit $haystack ("Heuhaufen") stets der Kontext, in dem etwas gesucht wird, mit $needle ("Nadel") das Gesuchte bezeichnet.
Auf die Signatur folgt eine ausführlichere Beschreibung. Besonders die Hinweise und Warnungen solltest du beachten. Funktionen, die als DEPRECATED gekennzeichnet wurden, werden in zukünftigen Versionen von PHP entfernt. Auf diese kannst du dich nicht verlassen; dein Code könnte nach einem Update von PHP nicht mehr funktionieren.
Ein Beispiel sagt in der Programmierung meist mehr als viele Worte, deswegen findet sich zu jeder Funktion meist eines oder mehrere Anwendungsbeispiele, die alle Argumentkombinationen vorstellt und Stolperfallen aufzeigt.
Abschließend werden unter "Siehe auch" alternative Funktionen für ähnliche Anwendungsfälle aufgezeigt. Auch das ist ein Weg, eine dir unbekannte Funktion zu finden. Bei strpos wirst du etwa auf strrpos hingewiesen, welches dir die letzte Position eines Zeichens aufzeigt.

## Die Benutzerkommentare

Unterhalb aller Handbuchseiten findest du die Benutzerkommentare. Diese sind in Englisch verfasst und werden von (meist) erfahrenen PHP-Benutzern eingereicht. Diese Kommentare weisen auf Dinge hin, die im Handbuch keine Erwähnung finden, oder bieten Lösungen für häufige Problemstellungen.

## Übung

Das bereits angesprochene Beispielprojekt (wir werden darauf zurückkommen, wenn du die Grundlagen kennst) soll eine Funktion anbieten, eine zufällige Buchvorstellung anzuzeigen. Die Bücherseiten wurden bereits in (statischen) Templates mit den Namen "buch1.tpl.php" bis "buch20.tpl.php" abgespeichert, die Nummerierung ist durchgängig. Wie kannst du nun eine zufällige Seite anzeigen? Tipp: Die Funktion für eine zufällige Zahl ist mt_rand. Schlage im PHP-Handbuch nach, welche Argumente die Funktion erwartet.

# Praktische Einführung: Arrays

Websiteentwicklung PHP Praktische Einführung Arrays
Du wartest wahrscheinlich schon gespannt darauf, Formulare auszuwerten und endlich Interaktivität zu haben. Bevor du das tun kannst, fehlt noch das Verständnis eines weiteren Konstrukts: Den Arrays.

## Was ist ein Array?

Ein Array ist ein weiterer Typ in PHP. Viele Anfänger tun sich schwer mit Arrays, insbesondere wenn sie in mehrere Dimensionen gehen. Deswegen versucht dieses Kapitel, dir Arrays so anschaulich wie möglich näherzubringen.
* Hinweis
* Vielleicht kennst du Arrays bereits aus anderen Programmiersprachen (z.B. C). In PHP ist der Begriff von Arrays viel weiter gefasst und vereint das Konzept von numerischen Arrays, Maps, Dictionaries, Listen und anderen.
Arrays sind wie Regalfächer, die man modular aneinander hängen kann. Die Fächer ("Elemente") haben eine Beschriftung (Der Schlüssel, bzw. "Key") und einen Inhalt (Wert, bzw. "Value"). Außerdem sind sie in einer bestimmten Reihenfolge angeordnet, die nicht unbedingt mit ihrer Beschriftung übereinstimmen müssen. Innerhalb von Regalfächern können sich ebenfalls Regale befinden.

## Arrays mit array definieren

Die erste Möglichkeit, ein Array zu definieren, ist das Sprachkonstrukt array:
$leeres_array ist, wie der Name schon sagt, ein leeres Array mit keinem Element. Du kannst dir den Inhalt eines Arrays mit var_dump oder mit print_r anzeigen lassen. Das leere Array wird mit
folgende Ausgabe erzeugen:
Das Array $himmelsrichtungen sieht mit print_r so aus:
Die Werte in den Klammern sind die Schlüssel, bzw. Fächerbeschriftungen, um im Bild zu bleiben. In der Programmierung bekommt das erste Element immer den Schlüssel 0, nicht 1.
Du kannst mit array auch direkt die Schlüssel festlegen:
führt zu folgender Struktur:
Das geht sowohl mit Strings als Schlüsseln, als auch mit Integers, und sogar in beliebiger Kombination. Werden zunächst Schlüssel definiert und dann wieder auf automatische Schlüssel zurückgegriffen, wird PHP den höchsten numerischen Schlüssel nehmen und eins dazuaddieren:
erzeugt folgenden Array:
Wie du siehst, sind die Elemente in der Reihenfolge, in der du sie festlegst.

## Auf Werte eines Arrays zugreifen

Um auf einen Wert in einem Array zuzugreifen, verwenden wir eckige Klammern:
Genauso können wir auch Werte neu setzen oder neue Elemente hinzufügen:
Bei der Zuweisung (nicht beim Auslesen) dürfen wir auch den Schlüssel weglassen, um neue Werte hinzuzufügen:
Die Schreibweise mit ist besonders in Schleifen hilfreich.

## Mehrdimensionale Arrays

Wenn du das Konzept von Arrays bis zu diesem Punkt nicht ganz verstanden hast, solltest du noch ein wenig experimentieren, denn jetzt gehen wir eine Stufe höher. Oder besser gesagt: tiefer.
Sieh dir einmal folgenden Code an:
Es entsteht in $kunden folgende Struktur:
Was ist geschehen? Wir haben zwei Arrays in ein Array abgelegt. Ein so verschachteltes Array heißt mehrdimensionales Array, in diesem Fall ist es zweidimensional, wobei auch deutlich mehr Dimensionen möglich (aber natürlich nicht immer sinnvoll) sind.
Wir können nun so auf die Werte der tieferen Arrays zugreifen:

## Nützliche Funktionen im Zusammenhang mit Arrays

* isset gibt zurück, ob eine Variable oder ein Schlüssel in einem Array existiert.
* unset löscht eine Variable oder ein Element aus einem Array.
* count gibt die Anzahl der Elemente eines Arrays zurück

## foreach

Nun lernst du deine erste Kontrollstruktur kennen: foreach. Zu Kontrollstrukturen zählen Schleifen und Bedingungen, aber auch include. foreach ist eine Sonderform der Schleife. Mit ihr kannst du durch alle Elemente eines Arrays iterieren.

### foreach ohne Schlüssel

Die foreach-Schleife liest sich als: "Für jedes Element im Array $kunden, dessen Wert du der Variable $kunde zuweist, führe die Anweisungen innerhalb der geschweiften Klammern aus". Die geschweiften Klammern begrenzen bei den beiden Haupttypen von Kontrollstrukturen, Schleifen und Bedingungen, die auszuführenden Anweisungen. Übrigens bleiben die Variablen auch außerhalb der geschweiften Klammern gültig.
* Hinweis
* Auch hier gibt es eine gängige Konvention: Für jede Verschachtelung mit geschweiften Klammern werden die Anweisungen weiter eingerückt, üblicherweise mit vier Leerzeichen, hier sind es zwei. Verwende zum Einrücken nicht die Tabulator-Taste, außer dein Editor ist so eingestellt, dass ein Tab automatisch in Leerzeichen umgewandelt wird.

### foreach mit Schlüssel

Es gibt noch eine zweite Variante, die foreach-Schleife zu verwenden:
Diese Schreibweise von foreach erlaubt es, auch die Schlüssel zwischenzuspeichern.

### foreach und Referenzen

$value ist normalerweise eine ganz normale Zuweisung, also eine Kopie des Wertes im Array. Es ist allerdings auch möglich, eine Referenz zu verwenden (mehr zu Referenzen findest du außerhalb dieser Einführung unter Referenzen). Das folgende Beispiel demonstriert dies:
Das Array $array hat jetzt die Werte 2, 6, 8 und 10, da du den Referenzoperator & (Kaufmännisches Und) verwendet hast. unset stellt danach noch sicher, dass die letzte Referenz, die auch nach der Schleife noch besteht, zerstört wird.

# Praktische Einführung: Benutzereingaben und Sicherheit

Websiteentwicklung PHP Praktische Einführung Benutzereingaben und Sicherheit
Bevor es nun endlich an Interaktivität geht, musst du zuvor einiges über Sicherheit wissen. Überspringe keinesfalls diesen Abschnitt! Der schwerwiegendste Anfängerfehler ist es, nicht auf die Sicherheit zu achten. Durch Sicherheitslücken können andere:
* deine Datenbank leeren
* Passwörter und andere Daten deiner Benutzer auslesen
* Viren in die Seite einfügen
* selbst "passwortgeschützte" Verzeichnisse auslesen und Dateien schreiben
* sich als andere Benutzer ausgeben
und vieles, vieles mehr. Es gibt keinen hundertprozentigen Schutz, aber du kannst alles tun, was in deiner Macht steht.

## Die goldene Regel

Die wichtigste Regel lautet:
Vertraue keiner Benutzereingabe!
Natürlich will dir nicht jeder Benutzer schaden, aber leider kann man nicht davon ausgehen, dass alle Benutzer harmlos sind. Diese Regel sagt aber noch mehr: Anstatt Benutzereingaben nach gefährlichen Zeichen zu durchsuchen, wende bei allen Benutzereingaben die gleichen Methoden an, gehe also vom schlimmst möglichen Fall aus.

## Herkunft von Benutzereingaben

Die zweite Regel lautet:
Alle Benutzereingaben sind unbekannter Herkunft.
Nur weil eine Eingabe im superglobalen Array $_COOKIE steht, heißt das nicht, dass der Benutzer wirklich ein Cookie auf seinem Computer hat. Auch muss der Benutzer kein Formular ausfüllen, um einen $_POST abzusetzen. Selbst der User-Agent (die Browserkennung) muss nicht von einem Browser stammen. Tatsächlich kannst sogar du mit einem einfachen PHP-Skript ein virtuelles Formular absenden, das sich hinter einem Browser deiner Wahl versteckt.
Versuche daher erst gar nicht, dich auf JavaScript oder HTML zwecks Validierung zu verlassen. Diese Mittel sind für den Benutzer gedacht, um noch bei der Eingabe ein Feedback darüber zu bekommen, ob seine Eingabe gültig ist.

## Wo landen Benutzereingaben in PHP?

Benutzereingaben schreibt PHP in die superglobalen (d.h. immer im Skript verfügbaren) Variablen $_GET, $_POST, $_COOKIE sowie in einigen Elementen von $_SERVER. Die Inhalte von $_SESSION liegen dagegen auf deinem Server. Sobald du allerdings Benutzereingaben in Variablen, in Datenbanken, Sessions oder wo auch immer abspeicherst, musst du auch diese Quellen als unsicher betrachten.

## Magic Quotes und Register Globals

Die Entwickler von PHP hatten zwei Features entwickelt, die seit PHP 5.3 deprecated (veraltet) sind und in einer der nächsten Versionen entfernt werden. Sie sind in den neueren Versionen (wie sie z.B. von XAMPP mitgeliefert werden) bereits in der php.ini deaktiviert.

### Register Globals

Die Direktive register_globals ist für sich genommen nicht gefährlich. Anstatt in den superglobalen Arrays werden Benutzereingaben direkt als Variablen im Code registriert. Das bringt allerdings einige Probleme mit sich, da man in PHP Variablen nicht initialisieren muss. Mit register_globals = on weiß man häufig gar nicht, ob eine Variable eine Benutzereingabe ist oder von einer Bedingung stammt.
Beachten musst du in der heutigen Zeit nichts mehr, da die Direktive standardmäßig auf off steht. Ist sie an, so schalte sie in der php.ini ab. Hast du in einer Shared-Webhost-Umgebung keinen Zugriff auf die php.ini, bitte deinen Webhoster, diese Direktive schleunigst abzustellen.

### Magic Quotes

Mit den Magic Quotes wollten die Entwickler von PHP zuvorkommend sein und dabei helfen, SQL-Injections vorzubeugen. Die Magic Quotes wenden auf alle Benutzereingaben die Funktion addslashes an, die bestimmte Zeichen escaped. Das ist gut gemeint, bringt aber eine Reihe von Problemen mit sich:
* strlen wird ein für die Datenbank falsches Ergebnis liefern
* statt addslashes sollte man die Funktion speziell für seinen Datenbanktyp verwenden
* das Anwenden auf alle Eingaben führt zu einer Leistungsminderung
Wenn du sicher weißt, dass dein Skript nur auf Servern mit magic_quotes = off verwendet wird (wie es seit 5.3 standardmäßig der Fall ist), brauchst du dir auch hierum keine Gedanken machen. Möchtest du allerdings portablen Code schreiben, musst du prüfen, ob die Direktive magic_quotes aktiv ist, und je nachdem die Backslashes mit stripslashes entfernen.
Den aktuellen Wert der Direktive erfährst du mittels der Funktion get_magic_quotes_gpc.

## Häufige Angriffstypen

Hier können nicht alle möglichen Angriffsvektoren aufgezeigt werden, lediglich einige wenige Gefahrenstellen. Solange du dich allerdings an die Goldene Regel hältst, wirst du dir diese Gefahren denken können.

### Angriff auf das Dateisystem

Alle folgenden Befehle sind gefährlich:
Es gibt kaum sichere Filtermöglichkeiten für Pfadangaben. Wende stattdessen die Whitelisting-Methode an: Erstelle eine Liste von möglichen Eingaben, z.B. in einem Array oder in der Datenbank, und speichere darunter die Pfadangaben bzw. Dateinamen ab.

### SQL-Injections

Wird nun vom Benutzer der (vorhandene) Benutzername "Max" und als Passwort "' OR 1 = 1" übergeben, liest sich der Query so:
Als Ergebnis wird der Benutzer eingeloggt, ohne das Passwort zu kennen.
Um die gefährlichen Zeichen (wie das einfache Anführungszeichen) los zu werden, gibt es mehrere Möglichkeiten.

#### Casten

Bei Zahlen und Booleans bietet es sich an, die Benutzereingaben zu Casten. Integers, Booleans und Floats können von Natur aus keine gefährlichen Zeichen enthalten:
Aufpassen musst du bei Zahlen, die eine Null am Anfang haben, beispielsweise Postleitzahlen oder Telefonnummern. Das musst du allerdings bereits bei der Planung der Datenbank, und diese Daten sowohl dort als auch in PHP als Strings behandeln.

#### Escapen

Alle Variablen, die du nicht zu Integern, Floats oder Booleans gecastet hast, musst du escapen. Dazu kannst du in der Regel die Funktion deiner Datenbank verwenden. Bei MySQL wäre dies mysql_real_escape_string:
Wenn du den universalen Adapter PDO benutzt, kannst du die Methode quote verwenden. Mehr über PDO im entsprechenden Kapitel.

#### Verwendung von Prepared Statements

Benutzt man Prepared Statements, also vorbereitete Abfragen, kümmert sich der Datenbanktreiber automatisch um das Escapen der Zeichen. Verwendet man ausschließlich Prepared Statements und benutzt im vorbereiteten Query selbst keine Benutzereingaben, ist man vor SQL-Injections ausreichend geschützt.
Beispiel für ein Prepared Statement mit PDO:
* Hinweis
* MySQL unterstützt Prepared Statements ab Version 4.1. Die PHP-Funktionen mysql_* kennen diese nicht, stattdessen solltest du mysqli oder, noch besser, PDO verwenden.

### Cross Site Scripting (XSS)

Beim Cross Site Scripting (XSS) wird JavaScript- oder HTML-Code eingefügt und so dein Layout zerstört oder im schlimmsten Fall ein Besucher mit gefährlichem Code (z.B. Viren) konfrontiert. Eine detaillierte Erklärung von XSS findest du im Wikipedia-Artikel Cross Site Scripting. Für den Moment reicht es, wenn du weißt, dass alle Benutzereingaben bei der Ausgabe entweder zu unschädlichen Integers, Floats oder Booleans gecastet oder mittels htmlspecialchars escaped werden müssen.
Die Funktion wandelt alle "&", "<" und ">" in ihre Escapesequenzen "&amp;", "&lt;" und "&gt;" um.
Auch Werte in deiner Datenbank können aus Benutzereingaben entstanden sein. Deshalb musst du auch bei Anzeige dieser die Funktion htmlspecialchars anwenden.

### Cross Site Request Forgery (XSRF)

Bei Cross Site Request Forgery (XSRF) wird eine Benutzereingabe getätigt, obwohl der Benutzer gar nicht die Absicht dazu hatte. Das kann z.B. durch einen manipulierten Link oder ein fremdes Formular geschehen. Dem kannst du entgegenwirken, indem du für sensible Aktionen (in SQL gesprochen: UPDATE und DELETE) auf der Seite des Formulars oder des Links ein Token erzeugst und in der Session abspeicherst. Anschließend musst du das per Link oder Formular übergebene Token mit dem gespeicherten vergleichen.

## Keine Informationen preisgeben

Wenn dein Skript für die Öffentlichkeit freigegeben wird ("Produktionsumgebung"), setze in der php.ini die Direktive display_errors auf 0 und starte den Server neu. PHP-Fehler, die möglicherweise interne Details enthalten, werden dann nicht mehr angezeigt. Wenn du eine Funktion geschrieben hast, die bei jedem Query mögliche Fehler anzeigt, mache sie von einer Konstante (z.B. "DEBUG") abhängig, die du im Produktionsbetrieb auf false setzt.
Man kann auch durch Ausschalten der Direktive expose_php in der php.ini und Umstellen der zu parsenden Dateierweiterungen auf z.B. .html PHP verstecken, aber diese "security through obscurity" (Sicherheit durch Verschleierung) wird einen ernsthaften Angriffsversuch auf dein System nicht verhindern.

## Eigene Macht einschränken

Wenn ein Skript eine Funktion nicht benötigt, sollte es diese auch nicht bekommen. Wenn du z.B. nie eine Datei mit fopen oder include auf einem entfernten Server öffnest, kannst du die Direktiven allow_url_fopen und allow_url_include in der php.ini deaktivieren.
Ein weiteres Beispiel dieses Prinzips sind sensible Daten wie etwa Kontonummern. Vielleicht kennst du die Methode, dass Kontonummern dem Benutzer teilzensiert gezeigt werden (etwa 12****). Aber auch schon das PHP-Skript kann einen solch eingeschränkten Zugriff bekommen: Die Kontodaten werden in einer gesonderten Tabelle der Datenbank gespeichert, für die das Skript nur Schreibrechte hat, die zensierte Kontonummer erfährt es über eine gespeicherte Prozedur der Datenbank (Siehe Wikibook Einführung in SQL: Prozeduren).

## Sessions

Für Sessions gibt es weitere Sicherheitsregeln, die du im entsprechenden Kapitel Sessions findest.

# Praktische Einführung: Benutzereingaben verwenden

Websiteentwicklung PHP Praktische Einführung Benutzereingaben verwenden

## Übergabe von Parametern per GET

Die einfachste Möglichkeit, Benutzereingaben zu verarbeiten, ist GET. Sicher sind dir bei URLs schon die Zeichen ?, = und & aufgefallen. Das Fragezeichen leitet nach dem Dateinamen die Argumentkette ein, das Gleichheitszeichen weist einem Bezeichner einen Wert zu. Das kaufmännische Und trennt schließlich die Argumente voneinander.
Ein Rechner für Währungen könnte z.B. eine solche URL haben:
Wenn dieses PHP-Skript aufgerufen wird, werden diese im superglobalen Array $_GET als die drei Elemente "from" (mit dem Wert 'dollar-us'), "to" ('euro') und "amount" ('10') abgelegt.

### Beispiel

show_get.php:
* Hinweis
* &amp; steht in HTML für &, da & für Zeichenersetzungen reserviert ist.
Dieses Beispiel zeigt dem Benutzer die Aktion an, die er ausgewählt hat. Du kannst auch selbst die URL in der Adresszeile des Browsers verändern und beobachten, was geschieht. Die Eingabe von <script type='text/javascript'>alert('XSS!');</script> zeigt dir, warum das vorige Kapitel wichtig ist.
GET hat den Vorteil, dass kein Formular zur Argumentübergabe benötigt wird. Allerdings sind URLs in der Länge begrenzt; daher ist für Daten wie etwa Text die POST-Methode besser geeignet.

## Formulare

Formulare bieten dem Benutzer die Möglichkeit, selbstständig Eingaben zu tätigen. Formulare verwenden in der Regel POST, es ist aber genauso möglich, GET zu benutzen:
show_get.php:
Die gewünschte Übertragungsmethode wird im Attribut method des form-Tags festgelegt, das Ziel des Formulars im Attribut action. Der Name der Eingabefelder entspricht dem Schlüssel im $_GET- bzw. $_POST-Array. Die Anzeige wurde leicht verändert: Es wird nun auf das Array $currencies zugegriffen, um nicht den programminternen Schlüssel, sondern die vollständige Bezeichnung der Währung anzuzeigen.

## POST

Um ein Formular mittels POST zu versenden, musst du lediglich das Attribut method auf "post" umstellen.

## Checkboxes

Um Checkboxes ("Kontrollkästchen") in PHP verwenden zu können, müssen die Boxen einer Gruppe als Array importiert werden:
Durch die beiden eckigen Klammern wird PHP angewiesen, ein Array mit diesem Namen zu erstellen und jeden angekreuzten Wert als ein neues Element hinzuzufügen. Dieses Array ist dann unter $_POST['fruits'] verfügbar. Ohne Klammern würde PHP den Wert von "fruits" mit der jeweils zuletzt angekreuzten Checkbox überschreiben.

# Praktische Einführung: Bedingungen

Websiteentwicklung PHP Praktische Einführung Bedingungen
Nun weißt du zwar, wie du auf Benutzereingaben aus GET und POST zugreifen kannst, aber nicht, wie man auf unterschiedliche Eingaben reagiert. Zu diesem Zweck wirst du in diesem Abschnitt eine neue Form der Kontrollstruktur kennen lernen: Die Verzweigungen bzw. Bedingte Anweisungen.

## Was ist eine Verzweigung?

Verzweigungen ermöglichen Programmen, Bedingungen zu überprüfen und je nachdem, ob sie erfüllt wurden oder nicht, Anweisungen auszuführen. In gewisser Weise "entscheidet" also das Skript über die weitere Vorgehensweise.

## if

Die einfachste Verzweigung in PHP ist die if-Verzweigung:
Dieses Konstrukt liest sich als: "Wenn die Aussage in der Klammer wahr ist, führe die folgende Anweisung aus." Die Bedingung wird immer auf einen boolschen Wert zurückgeführt, also true oder false ergeben. Da in diesem Beispiel die Aussage immer wahr ist, wird dementsprechend auch die echo-Anweisung stets ausgeführt. Umgekehrt werden wir bei diesem Code
nie eine Ausgabe sehen.

### Mehrere Anweisungen

Es ist auch möglich, mehrere PHP-Anweisungen von der Bedingung abhängig zu machen. Dazu werden diese von geschweiften Klammern umschlossen, wie du das bereits von foreach kennst:
* Hinweis
* Anders als in C haben Variablen in PHP innerhalb einer Kontrollstruktur den selben Gültigkeitsbereich wie außerhalb der geschweiften Klammern.

### Operatoren

Die Aussagen innerhalb der Klammern können Operatoren verwenden.

#### Vergleichsoperatoren

Mit Vergleichsoperatoren können Aussagen über das Verhältnis zweier Werte zueinander getroffen werden:
Als Ausgabe erhältst du:
Jetzt siehst du auch, warum es wichtig ist, das einfache Gleichheitszeichen in PHP stets als Zuweisung zu sehen. Würden wir nämlich
schreiben, ergäbe die Ausgabe
Mit $a = $b wird $a der Wert von $b zugewiesen, und das Ergebnis dieser Zuweisung, also 4, als Bedingung verwendet. Nach den Umwandlungsregeln für den Typ Boolean sind Integer außer 0 immer true, somit auch die Bedingung.
Für Gleich und Ungleich existiert noch eine typensichere Variante mit je einem Gleichheitszeichen mehr: === und !==. Aussagen gelten dann als wahr, wenn die Werte links und rechts vom Operator absolut gleich (ungleich) sind, sowohl vom Wert, als auch vom Typ:
Eine vollständige Liste der Vergleichsoperatoren findest du im ausführlichen Kapitel Operatoren.

#### Logische Operatoren

Die zweite Gruppe der Operatoren, die speziell für Verzweigungen existieren, sind die logischen Operatoren. Der einfachste davon ist "Nicht" (!). "Nicht" kehrt eine Aussage ins Gegenteil:
true wurde hier zu false, somit ist die gesamte Bedingung unwahr. Ein etwas komplexeres Beispiel:
Von solchen Konstruktionen ist aber abzuraten. Das Beispiel lässt sich leicht auf (5 > 4) umschreiben.
Um Aussagen logisch zu verknüpfen, verwendet man die Operatoren "Und" (&&), "Oder" (||) und "Exklusives Oder" (xor):
Auch diese lassen sich zu komplexeren Bedingungen zusammenfügen:
"Hallo Welt" wird ausgegeben, da
ausgewertet wird zu

### else und elseif

Mit else kannst du Anweisungen festlegen, die nur ausgeführt werden, wenn die Bedingung nicht zutrifft:
Außerdem lässt sich mit elseif auch für diesen Fall eine weitere Bedingung stellen:

## switch

Wenn eine Variable auf viele verschiedene Aussagen hin überprüft werden soll, wird die Sache mit if schnell unübersichtlich. Der folgende Code gibt das Zahlwort einer eingegebene Ganzzahl von 1 bis 5 aus:
In dieser if-Abfrage wird ein und dieselbe Variable mit zahlreichen Werten verglichen. Für diese Aufgabe gibt es eine spezielle Kontrollstruktur: switch.
Sehen wir uns die einzelnen Bestandteile der Anweisung einmal genauer an.

### switch

switch leitet die Kontrollstruktur ein. In der Klammer kann ein beliebiger Wert stehen, z.B. eine Variable, eine Konstante oder der Rückgabewert einer Funktion; Vergleichs- und logische Operatoren jedoch nicht.

### case

Mit case wird der zu vergleichende Wert festgelegt. switch vergleicht immer typenschwach, als ob du eine if-Abfrage mit dem Operator == geschrieben hättest. Alle Anweisungen nach case werden ausgeführt, sie müssen, anders als bei if, nicht in geschweifte Klammern gesetzt werden.
Es ist auch möglich, mehreren Fälle die gleichen Anweisungen zuzuordnen:
Dieses Beispiel funktioniert wie eine Oder-Verknüpfung (||) der Fälle.

### break

Nach dem Anweisungsblock solltest du das Schlüsselwort break setzen. Es bewirkt in den Anweisungsblöcken aller Kontrollstrukturen (also auch z.B. in if oder foreach) einen "Ausbruch" aus der gesamten Struktur. Betrachten wir, was ohne break geschehen würde:
Bei $number = 10 ist noch alles in Ordnung:
Mit $number = 5 zeigt sich allerdings das Problem:
Wie bereits beschrieben: Alle Anweisungen nach case werden ausgeführt. Da kein break erfolgt, geschieht dies mit allen drei echos.

### default

default ist gewissermaßen das else aus dem Ursprungsbeispiel. default ist optional und immer wahr (wie der Ausdruck $number == $number).

## Trinitätsoperator

Der Trinitätsoperator (engl. "ternary operator", weswegen auch oft als Ternäroperator bezeichnet) gehört nicht zu den Kontrollstrukturen, sondern zu den Vergleichsoperatoren und findet vor allem bei Zuweisungen Verwendung.

### Beispiel

Auf der höchsten error_reporting-Stufe wird dir ein E_NOTICE-Fehler angezeigt, wenn du auf eine nicht vorhandene Variable zugreifen möchtest. Dieser Hinweis ist hilfreich, da so Tippfehler schneller gefunden werden können. Allerdings kommt es gerade bei Benutzereingaben häufiger vor, dass der Wert (respektive Schlüssel im Array) nicht gesetzt worden ist.
Nehmen wir einmal an, alle Seiten unseres Beispielprojekts sollen über eine einzige Datei index.php laufen, sodass wir Dinge wie die Herstellung der Datenbankverbindung zentral an einer Stelle verarbeiten können. Die gewünschte Unterseite kommt mittels $_GET-Parameter "page". Wenn jetzt allerdings jemand unsere Seite www.example.com aufruft, existiert dieser Schlüssel nicht. Hier kommt der Trinitätsoperator ins Spiel:
Der Variable $page wird das Ergebnis dieses Ausdrucks zugewiesen: Wenn der Schlüssel 'page' in $_GET existiert, entspricht dies dem Wert, ansonsten wird 'index' zugewiesen. Das entspricht:

## Praktische Anwendung

Genau das letzte Beispiel wollen wir in die Tat umsetzen: Unsere fiktive Website soll ausschließlich über eine zentrale index.php gesteuert werden, die einzelnen Inhalte finden sich in Templates wieder. Aus den im Kapitel Benutzereingaben und Sicherheit vorgestellten Gründen ist dringend davon abzuraten, den Wert von 'page' direkt ins Dateisystem, etwa in der Form include $page . 'tpl.php' zu übersetzen. Stattdessen definieren wir eine Liste an gültigen Seiten.

### Ausblick

Soeben hast du die Urform eines Front-Controllers kennengelernt. Dieser nimmt Anfragen entgegen, führt die auf jeder Seite nötigen Schritte aus und leitet die Aufgaben an Untercontroller weiter.
Später wird eine Datenbank für uns die Templates bereitstellen, zusammen mit der Information, ob weitere Logik vorhanden ist.

# Praktische Einführung: Datenbanken

< Websiteentwicklung: PHP PDO (PHP-Database-Object)

## PDO

Eine moderne, objektorientierte Schnittstelle zu vielen Database-Management-Systemen. Sie ist bereits seit PHP 5.1 als Modul eingebunden und erlaubt ein umfassendes Databasemanagement in einer OOP-Umgebung PDO Die PDO-Schnittstelle geht in die Kategorie objektrelationales Mapping von SQL-Anweisungen. Die SQLs sind in die PDO-Query-Klassen eingebunden.
Inhaltsverzeichnis
* Verbindung aufbauen
* query
* fetch

# Praktische Einführung: Schleifen

Schleifen sind Kontrollstrukturen, mit deren Hilfe man Codeabschnitte beliebig oft wiederholen kann. In PHP gibt es grundsätzlich drei (bzw. vier) verschiedene Arten von Schleifen.

## while

Eine while-Schleife wird so oft wiederholt, wie die Bedingung im Schleifenkopf als true ausgewertet wird (siehe dazu auch das Kapitel zu Castings). Dabei ist zu beachten, dass in jedem Durchlauf immer zuerst geprüft wird, ob die Bedingung "wahr" ist und danach ggf. der Schleifenrumpf ausgeführt wird. Wenn die Abbruchbedingung nicht wahr ist, wird das Programm nach der Schleife fortgesetzt. Es kann also sein, dass diese Schleife auch gar nicht ausgeführt wird. Daher nennt man die While-Schleife eine Kopf-gesteuerte Schleife.
In diesem Beispiel würde der Schleifenrumpf dreimal ausgeführt. Sobald $i den Wert 4 erhält, ist die Bedingung $i < 4 (in diesem Fall also 4 < 4) nicht mehr wahr und somit wird die Schleife für 4 kein weiteres Mal ausgeführt.

### do-while

Die do-while-Schleife funktioniert so ähnlich wie die while-Schleife, aber mit dem entscheidenden Unterschied, dass die Prüfung der Bedingung bei jedem Schleifendurchlauf immer erst nach dem Ausführen des Schleifenrumpfes geschieht.
Im Gegensatz zur while-Schleife wird hierbei an den Anfang des Rumpfes das Schlüsselwort do gestellt und das while mit der Abbruchbedingung (wie es schon in der normalen while-Schleife am Kopf des Rumpfes zu finden ist) an das Fuß bzw. Ende des Rumpfes.
Im Unterschied zur while-Schleife wird die do-while-Schleife auf jeden Fall mindestens einmal ausgeführt, da die Abbruchbedingung erst nach dem Ausführen am Ende bzw. am Fuß des Rumpfes geprüft wird. Daher nennt man sie auch eine Fuß-gesteuerte Schleife.

## foreach

Die foreach-Schleife wurde bereits im Kapitel der Arrays behandelt.

## for

Die for-Schleife ist die komplizierteste Schleife in PHP. Meistens wird sie dazu verwendet um über Arrays (oder andere abzählbare Strukturen) zu iterieren. Der Schleifenkopf der for-Schleife besteht aus drei unterschiedlichen Teilen, die voneinander durch ein Semikolon getrennt sind:
* Der erste Abschnitt wird vor dem ersten Durchlauf der Schleife ausgeführt.
* Der zweite Abschnitt wird vor dem Beginn jedes einzelnen Durchlaufs ausgeführt. Außerdem wird dieser Abschnitt auch als Schleifenbedingung verwendet. Die Schleife wird also solange wiederholt, wie der Ausdruck in diesem Abschnitt als true ausgewertet wird.
* Der dritte Abschnitt wird nach dem Ende jedes einzelnen Durchlaufs durchgeführt.
Wenn man den Schleifenkopf in diesem Beispiel analysiert, stellt man fest, dass im ersten Abschnitt (also vor dem allerersten Durchlauf) die Variable $i auf 0 gesetzt wird und dass im letzten Abschnitt (also nach dem Ende eines jeden Durchlaufs) der Wert von $i um eins erhöht wird.
Die Bedingung - also der zweite Abschnitt - gibt in diesem Beispiel solange true zurück, wie $i kleiner als 3 ist, da das Array $personen drei Elemente hat. Das bedeutet, dass die Schleife dreimal durchlaufen wird, wobei $i erst den Wert 0, beim zweiten Mal 1 und schließlich den Wert 2 hat.

## Weiteres
### break

Mit break lässt sich die Ausführung der Schleife an einem bestimmten Punkt unterbrechen. Ein simples Beispiel:

### continue

Mit continue lässt sich die Schleife an einer beliebigen Stelle fortführen.

# Vorwort

Websiteentwicklung PHP Vorwort

## Vorwort

Dieses Wikibook soll Ihnen nicht nur den Einstieg in PHP ermöglichen, sondern Sie umfassend über alle Möglichkeiten, die die Programmiersprache PHP bereit hält, informieren. PHP ist eine Sprache, die ganz am Anfang aus einer Sammlung von Perl-Skripten entwickelt wurde, sich hervorragend für Websiteentwicklungen eignet und sich mit ASP, Java, Perl, und Python vergleichen lässt. PHP ist in diesem Gebrauch ein immer weiter gewachsenes Bindeglied zwischen Webanwendungen und Datenbanken, aber auch C-Programmbibliotheken und -anwendungen.
Darüber hinaus kann PHP seit der Version 4.3 auch als CLI (Command Line Interface) genutzt werden und somit reiht sich die Skriptsprache auch in Sprachen wie Shell, Perl und Python an der Kommandozeile ein. Es bietet durch die implementierten Erweiterungen (extension) einen besonders vielseitigen Spielraum von Datenbankanbindungen über Grafik- und Flashanwendungserstellung bis hin zu XML-Parsern ein breites Spektrum an Einsatzmöglichkeiten.
PHP verbirgt dabei seine Herkunft nicht. Es lehnt sich syntaktisch an C an, in dem, wie unter *NIX üblich, der Quellcode (Source) geschrieben wird. Daher eignet es sich nicht nur als einfache Implementierung von Webanwendungen für C-Programmierer, sondern auch als leichter Einstieg für die Programmiersprache C.
Allgemeine Informationen oder Probleme mit PHP sowie speziell Probleme bei einem Skript, die Sie auch in Foren wie SelfHTML oder Nutzergruppen klären lassen wollen, sollten Sie immer erst eigene Recherchen im Internet vorangehen lassen. Denn es gibt eine Vielzahl von fertigen Skripten für so ziemlich jedes Problem. Insbesondere bei Schwierigkeiten mit der Sprache werden Sie nicht selten auf das Handbuch (http://www.php.net/manual/de/) zurückverwiesen.

# Beschreibung

Websiteentwicklung PHP Beschreibung
PHP (rekursive Abkürzung von PHP: Hypertext Preprocessor) ist eine serverseitige Open-Source-Skriptsprache, die vorwiegend zur Erstellung dynamischer Webseiten verwendet wird. Die aktuelle Version steht unter php.net zum Download zur Verfügung. Dort befindet sich ebenfalls eine hervorragende ausführliche Dokumentation der umfangreichen Funktionen. In der Wikipedia finden Sie nähere Informationen über PHP und seine Geschichte.

## Vorteile von PHP

* PHP ist leicht zu lernen – Umsteiger werden auf den ersten Blick die Ähnlichkeiten mit Java oder C++ erkennen und schon nach wenigen Minuten sollten sich die Meisten wie zu Hause fühlen. Neulinge können schnell in die Programmierung einsteigen und bald erste Ergebnisse im Browser betrachten.
* PHP ist frei verfügbar – Jeder kann den Quellcode von PHP einsehen und nach seinen Vorstellungen verbessern oder weiterentwickeln. Wer einfach nur PHP-Skripte entwickeln will, kann sich jederzeit kostenlos die Software herunterladen und auf seinem Rechner installieren.
* PHP ist vielseitig – Es sind PHP-Versionen für Unix, Windows, Mac OS und einige andere Plattformen verfügbar. Es kann als SAPI oder CGI mit dem Webserver kommunizieren und mit dem CLI kann man sogar Kommandozeilen-Skripte programmieren, oder kann über Milter zur Mailanalyse herangezogen werden. PHP hat standardmäßig viele Schnittstellen zu anderen Programmiersprachen und Datenbanken.
* PHP ist populär – Mittlerweile verwenden viele Millionen Internetseiten PHP. In unterschiedlichsten Einsatzgebieten und Webseiten, die von der einfachen Homepage bis zum Mega-Webportal reichen, hat sich PHP bereits bewährt.
* PHP ist gut dokumentiert – Die einfache Erlernbarkeit von PHP ist wohl vor allem der ausgesprochen guten Homepage zu verdanken. Allerdings gibt es auch endlos viele Bücher, Foren und Newsgruppen zum Thema PHP.

## Nachteile von PHP

* PHP hat bislang keinen Anwendungs-Server – Das heißt, alle Variablen müssen bei jedem Aufruf wieder neu geladen bzw. berechnet werden.
* PHP ist populär – Was oft ein Vorteil ist kann durchaus auch ein Nachteil sein. Schwachstellen in PHP oder PHP-Skripten können schneller und wirksamer ausgenutzt werden, weil viele potentielle Opfer verfügbar sind.
* PHP ist leicht zu lernen – Auch das kann ein Nachteil sein, weil deshalb viele PHP-Projekte ohne das nötige Hintergrundwissen verwirklicht werden. Die Folge davon ist, dass viele Websites gravierende Sicherheitsmängel aufweisen.
* PHP ist eine rein interpretierte Sprache und die erzeugten Programme damit vergleichsweise langsam in der Ausführung. Dies kann jedoch durch Verwendung von Op-Code-Caches ausgeglichen werden.
* PHP hat im Gegensatz zu anderen Skriptsprachen keine Möglichkeiten der Programmierung von Threads.

## Unterschiede der verschiedenen Formen PHPs

Es gibt Unterschiede der einzelnen Formen PHPs, die Sie kennen sollten, um bei wechselnden Anforderungen die beste Auswahl für den Einsatz treffen zu können.

## PHP als Webservermodul

PHP kann in einer ganzen Reihe von Webservern als Modul integriert werden. Zu den unterstützten Servern gehören derzeit AOLserver, Apache, caudium, Continuity Server, Netscape, Pi3web, Roxen, Sun, thttpd, Zeus und weitere (teils) veraltete Webserver.
PHP als Webservermodul eignet sich für leistungskritische Einzelprojekte, da nicht für jedes Skript ein neuer Prozess erstellt werden muss.
* Die Leistung eines Webservermoduls ist erheblich besser als die eines CGI-Binärs.
* HTTP-AUTH ist nur mit PHP als Modul möglich.
* PHP führt Code standardmäßig unter dem selben Benutzer und der selben Gruppe wie den Webserver aus, was zu Problemen mit der Sicherheit führen kann.
* Das Nachladen von PHP-Modulen durch dl ist auf multithreaded Servern nicht möglich.
* Jedes Skript wird in dem Verzeichnis ausgeführt, in dem es abgelegt wurde.

## PHP als CGI

Über CGI kann PHP mit jedem Webserver zusammenarbeiten. Es ist die Standardmethode und eignet sich für Shared Hosting.
* Die Leistung des CGI-Binärs ist erheblich schlechter, als die eines Webservermoduls. Daher wird PHP in den letzten Jahren vermehrt mit FAST-CGI genutzt.
* Es können mehrere differierende Versionen PHPs parallel genutzt werden.
* Für jedes Skript wird ein neuer Prozess gestartet. Daher ist es möglich, diese unter verschiedenen Benutzern und Gruppen auszuführen.
* Jedes Skript wird in dem Verzeichnis ausgeführt, in dem es abgelegt wurde.

## PHP als CLI

CLI wurde erstmalig mit Version 4.2.0 experimentell eingeführt und ist seit Version 4.3 offizieller Bestandteil.
* Mit Hilfe des CLI-Binärs kann man die gesamte Flexibilität und Funktionalität PHPs an der Kommandozeile nutzen. Es lassen sich eigene Administrationstools erstellen – ja sogar Daemons/Serveranwendungen schreiben. Mit der Erweiterung GTK sind auch GUI-Anwendungen möglich.
* Programme werden, anders als CGI-Skripte, im aktuellen Arbeitsverzeichnis der Kommandozeile ausgeführt. Dieses kann zu unerwarteten Fehlern beim Portieren/Ausführen von Skripten führen, welche für Webanwendungen geschrieben wurden.
* CLI öffnet beim Start die Streams stdin, stdout und stderr selbständig.
* Es kann sowohl als Datei abgelegten Code, als auch Code über den stdin ausführen.
* Einige Funktionen (z. B.: header) sind deaktiviert.

# Installation

Websiteentwicklung PHP Installation
Den Apache-WebServer gibt es inklusive unter anderem PHP4 und PHP5 als Distribution für verschiedene Systeme bei apachefriends.org. Dies erleichtert die Einrichtung speziell für Anfänger. Allerdings ist die Erfahrung bei einer solchen Installation nicht sehr hilfreich für spätere Konfigurationen und gewährt keinerlei Einblicke.

# Download

Laden sie sich PHP direkt von der Projektsite herunter. Der Direktlink zur Downloadseite ist www.php.net/downloads.php. Darüberhinaus werden unter snaps.php.net der aktuell in der Entwicklung befindliche Quellcode angeboten.
* Für *NIX-artige Betriebssysteme laden Sie den „Complete Source Code“ herunter,
* für Windows-Server mit Apache 1 oder Apache 2 verwenden sie das angebotene ZIP-Archiv und
* für Windows Server mit IIS, PWS oder Xitami verwenden sie das Installer-Programm (Danach der Installationsroutine folgen).
Fahren sie nun mit den Anweisungen für ihr Betriebssystem fort:
* Windows
* UNIX, Linux, Mac OS

# Windows
## Voraussetzungen für diese Anleitung

* ein funktionstüchtiges Betriebssystem
* Apache 1 oder 2 funktionierend (nur für Windows, unter Unix/Linux wird die Installation des Apaches gleich mit abgehandelt)
* Kenntnisse im Umgang mit Dateien und dem jeweiligen Betriebssystem

## Erstellen eines Apachemodules

Zur Einfachheit am besten die Daten im Verzeichnis c:\php entpacken, so dass die Daten direkt unter c:\php liegen. Ein beliebter Fehler entsteht beim entpacken, da die Entpackprogramme die Daten in c:\php\php ablegen, bitte unbedingt ändern so dass die Daten in c:\php liegen. Das ist Fehlerquelle Nummer 1.
Tipp: Am besten php klein schreiben, damit es später bei der Konfiguration des Apaches zu keinen Problemen kommt.
Hinweis: Auf das Verzeichnis c:\php und alle Unterordner/Dateien müssen alle Benutzer zugreifen können (Leseberechtigung).
Nun benutzen wir einen Trick, um eine spätere Aktualisierung von PHP zu vereinfachen. Es gibt in Windows eine sogenannte PATH-Variable, in der alle Systempfade eingetragen sind. Von dort aus können dann DLLs aufgerufen werden.
Unter Windows-XP-Installationen sind diese unter Start → Systemsteuerung → System → Erweitert → Umgebungsvariablen → Systemvariablen zu finden. Nun verändern wir den Eintrag mit Path über die Schaltfläche Bearbeiten und hängen an das Ende (ohne Anführungszeichen) "; c:\php" an.
Sollte die Datei php?ts.dll noch nicht in c:\php liegen, so bitte in den Unterordnern von c:\php suchen und nach c:\php kopieren.
Außerdem sollten jetzt, je nach Verwendungsbereich, folgende Dateien aus c:\php\sapi nach c:\php kopiert werden:
Hinweis: Hierzu sollten Sie sich PHP 4 herunterladen, denn in der Version 5 ist die Struktur sehr unterschiedlich. (Ordner /sapi existiert nicht!)
| Verwendungzweck | Datei |
| Webserver mit Apache 1 | php4apache.dll |
| Webserver mit Apache 2 | php4apache2.dll |
| Active Scripting | php4activescript.dll |

## Erstellen eines CGI-Programms

Hier ist Deine Mithilfe erforderlich!
Fahren sie nun mit Anpassen der Apache-Konfiguration fort.

# UNIX-artige Systeme
## Voraussetzungen

* ein funktionstüchtiges Betriebssystem
* einen Compiler (Vorzugsweise GCC)
* den Parsergenerator bison
* einen lexikalischer Generator (z. B. flex)
* das GNU-Programm make
* das GNU-Programm sed
* Kenntnisse im Umgang mit der Kommandozeile/Konsole
Hinweis: Die allermeisten Linux-Distributionen haben diese Programme bereits vorinstalliert. Insbesondere auf einigen Versionen von SuSE-Linux müssen Sie diese Programme zuerst installiert haben, wenn sie nicht über den Paketmanager installieren wollen!
Generell hat man zwei verschiedene Möglichkeiten auf einem GNU-Linux-System PHP und/oder Apache zu installieren. Der einfachere Weg ist den Paketmanager seiner Distribution dafür zu benutzen. Fühlen sie sich von mir dazu ermuntert, es sich nicht einfach zu machen! Sie haben so die Möglichkeit ein stückweit in das Innenleben eines Paketmanagers zu schauen und werden feststellen können, wie unflexibel dieser sein kann und welche Vielzahl an Möglichkeiten, die PHP mitbringt, er ihnen nicht erlaubt einzustellen.

## Installation über Paketmanager
### Debian und Derivate

Debian und davon abhängende Distributionen können PHP mit apt installieren. Dafür tippt man einfach in einer beliebigen Shell
bzw.
Abhängigkeiten werden automatisch geladen und installiert.

### Gentoo

Nachdem sie ihren portage tree aktualisiert haben, schauen sie, was portage alles installieren möchte:
Wie sie sehen, haben sie mit Gentoo fast dieselben Möglichkeiten, die ihnen auch beim manuellen Zusammenstellen von PHP zu Verfügung stehen. Wie üblich können sie alles über die USE-Variable bestimmen. Wie immer wird sich portage um alle Abhängigkeiten kümmern. Um PHP als Apache-Modul (Version 2.x), CGI-Binär und CLI zu kompilieren, gehen sie folgendermaßen vor:
Fahren sie nun mit Anpassen der Apache-Konfiguration fort.

### SuSE/openSuSE

Das Repository "http://download.opensuse.org/distribution/xxx/repo/oss" hinzufügen, der Platzhalter xxx steht für die Versionsnummer ihrer SuSE-Version. Ansschließend das Paket "php5" installieren.

## Installation aus dem Quellcode

Sie haben sich also dazu entschieden PHP manuell zu installieren? Richtig so! ;)
Nach dem Download des Quellcodes müssen sie diese nun entpacken. Ich empfehle ihnen, dies nicht über ein Programm mit GUI zu erledigen. Es spricht zwar nichts dagegen, aber zwingen sie sich dazu, so viel wie möglich mit der Konsole zu arbeiten. Sie werden feststellen, dass so aufgerufene Programme Arbeiten sehr schnell erledigen und es ist nunmal der Standardweg für alle administrativen Aufgaben an einem *NIX-System.
In der folgenden Beschreibung gehe ich davon aus, dass sie die Quellcode (php-x.x.x-tar.bz2) im Verzeichnis /opt/src abgelegt haben und ein Apache bereits vorinstalliert wurde:
Hinweis: Lesen sie sich die README eines Quellcodepakets immer durch. Hier finden sie weitere wertvolle Hinweise zur Installation, aber auch abweichende Handhabungen zu dieser Kurzanleitung.
Wenn dies das erste Mal sein sollte, dass sie Quellen selbst kompilieren, machen sie sich zunächst mit den Optionen des Konfigurationsskripts ./configure vertraut:
Sollte die Ausgabe zu lang für ihren Bildschirm sein, können sie mit einer Pipe und einen Pager arbeiten:
Zu den einzelnen Optionen lesen sie bitte auch Configure options im PHP-Handbuch!
Alle Optionen, die PHP-Erweiterungen kennzeichnen, die in dessen Quellcode enthalten sind, werden mit --enable-[NAME] oder --disable-[NAME] gesteuert. Bei diesen Erweiterungen müssen sie sich – anders als bei Erweiterungen, die über --with-[NAME] und --without-[NAME] gesteuert werden – nicht darum kümmern, dass weitere Programme aus dem Quellcode zu installieren sind.
Je nachdem welchen Webserver sie installiert haben, stehen ihnen verschiedene Möglichkeiten zur Verfügung PHP zu kompilieren. Im Folgenden werden sie genauer darüber informiert, wie sie ein CGI- oder CLI-Binär, ein Apachemodul für die Version 1.x oder ein Modul für die Version 2.x des Webservers erstellen können.
Vergewissern sie sich bitte unbedingt unter http://www.php.net/manual/de/security.php über die zwingend erforderlichen Optionen, die für die Sicherheit gesetzt werden sollten! Hierbei gilt es abhängig davon, welche PHP-Variante sie installieren wollen, Unterschiede zu beachten. Haben sie alles beachtet? Dann kann es jetzt losgehen. ;)

### CGI-/CLI-Binär erstellen

PHP stellt ihnen zwei unterschiedliche Binärprogramme zur Verfügung. Standardmäßig wird das CGI-Binär kompiliert und installiert. Dieses ist für das Common Gateway Interface eines Webservers gedacht. Durch die Option --enable-fastcgi wird das Programm um die Fähigkeit erweitert über FastCGI angesprochen zu werden und einen Parserserver bereitzustellen.
Setzen sie also nun ihre Konfiguration für das CGI-Binär:
Daraufhin wird das Shell-Skript configure seine Arbeit beginnen. Das Skript initialisiert eine Reihe von Tests, die im wesentlichen aus Prüfungen bestehen, ob benötigte C-Headerdateien vorhanden sind. Ist alles vorhanden wird das Skript am Ende Make-Dateien erstellen, mit deren Hilfe der GNU-Befehl make die Quellen kompilieren wird.
Gerade am Anfang ist es nichts ungewöhnliches, wenn configure nicht alle benötigten Komponenten vorfindet. Eine mögliche Fehlermeldung könnte beispielsweise so aussehen:
Diese Meldung zeigt an, daß eine benötigte C-Headerdatei nicht gefunden wurde und ist ein Indiz dafür, dass das Programm / die Bibliothek auf ihrem System nicht installiert wurde - jedenfalls aber nicht unter dem angegebenen oder den vom Entwickler dafür vorgesehenen Pfad.
Kompilieren sie nun die Quellen und schließen sie die Installation ab:
Da PHP sowohl das CGI- als auch das CLI-Binär unter dem mit --prefix benannten Pfad als php ablegen wird, kann immer nur ein Binär gebaut werden. Um ein CLI-Binär zu erhalten, gehen sie wie folgt vor:

### Modul für den Apachen 1.x erstellen

Beachten sie bitte die unter CGI-/CLI-Binär erstellen beschriebene Handhabung bei Fehlermeldungen des configure-Skriptes!
Obwohl derzeit zwei weitere Hauptversionen des beliebten Webserver Apache vorliegen, ist der Apache 1.3.x immer noch der am häufigsten eingesetzte HTTP-Server für produktive Webanwendungen. Für diese Version Apaches haben sie grundsätzlich zwei verschiedene Möglichkeiten, die Nutzung von PHP sicherzustellen.
Sie können aus dem PHP-Quellcode ein eigenes Modul erstellen, das vor der Installation des Apachen in dessen Quellcode abgelegt wird. Das Modul wird dann über dessen configure-Skript aktiviert. Dadurch ist es möglich den Apachen als Monolith-Binär mit PHP-Unterstützung aufzusetzen. Auch wenn es sich eingebürgert hat, Module von Zweitanbietern (Module, die nicht von der Apache Software Foundation herausgegeben werden) als shared object über mod_so zu betreiben, will diese Anleitung sie nicht bevormunden, sondern ihnen auch diese Möglichkeit aufzeigen:
Wenn sie PHP so nutzen möchten, beachten sie bitte, dass PHP sich ausschließlich über die Konfigurationsdateien (httpd.conf/.htaccess) manipulieren lässt und keinerlei php.ini mehr beachten wird! Weiterhin ist diese Variante der Nutzung auch aufwändiger, da sie mit jeder Aktualisierung von PHP oder dessen Erweiterungen gezwungen sind, den gesamten Server neu aufzusetzen.
Sie können aber auch den üblichen Weg beschreiten. Entpacken und kompilieren sie dazu zunächst die Quellen des Apachen. Der Apache wird in seinem bin-Verzeichnis eine Datei apxs anlegen. apxs ist ein in Perl geschriebenes Skript, welches als Standardschnittstelle für die Generierung von Modulen des Apachen dient.
Das so erstellte Modul wird Direktiven der php.ini stets beachten.

### Modul für den Apachen 2.x erstellen

Beachten sie bitte die unter CGI-/CLI-Binär erstellen beschriebene Handhabung bei Fehlermeldungen des configure-Skriptes!
Seit der PHP-Version 5.1 gilt das Modul für den Apachen 2.x nicht länger als experimentell. Gehen sie nach dem Entpacken und Kompilieren der Apache-Quellen folgendermaßen vor:
Darüber hinaus lässt sich PHP nunmehr auch als Filter kompilieren. Diese Option ist jedoch noch experimentell. Ein Filtermodul stellt Möglichkeiten für den Eingriff in die Verarbeitung einer Anfrage an den Server bereit, oder kann den zu servierenden Inhalt von Ressourcen manipulieren. Beides sind keine klassischen Einsatzfelder von PHP. Daher wird an dieser Stelle nicht näher darauf eingegangen.
Hinweis: Auf Multithreaded Server, wie dem Apachen z. B. mit mod_worker können sie keine PHP-Module nach dessen Start nachladen. Überdenken sie daher bei der Erstellung des Servermodules sorgfältig, welche Erweiterungen sie tatsächlich für ihre Webprojekte benötigen/benötigen werden!

### PHP in Module gliedern

Der Apache macht es vor die Funktionalität in einzelne Module zu gliedern. Dies kann man auch mit den PHP-Erweiterungen (extension) machen. Es ist vorteilhaft, wenn sich die einzelnen C-Bibliotheken der Erweiterungen aktualisieren. So muss man nicht immer PHP neu aufsetzen; es genügt die einzelne Erweiterung neu zu kompilieren. Auch wenn in der Ausgabe von ./configure --help nachzulesen ist, dass nicht alle Erweiterungen als Modul gebaut werden können, so ist dies schlichtweg falsch.
Anhand des folgenden Beispiels, in dem ein CLI-Binär erstellt wird, möchte ich ihnen kurz darlegen, wie sie alle Erweiterungen als Module kompilieren können.
Hinweis: Sie müssen GNU-autoconf installiert haben! Löschen sie den PHP-Quellcode nicht vor dem Neuerscheinen einer aktuelleren Version, denn die dort abgelegten C-Headerdateien sind wichtig, wenn sie während des Betriebs feststellen sollten, dass sie weitere PHP-Module benötigen.
Erstellen sie sich als erstes ein PHP-Binär, dass nichts weiter kann, als die ureigene Sprache auszuführen:
Hierbei werden im Verzeichnis /opt/php/bin die Programme php, phpize und php-config erstellt. phpize ist ein Shell-Skript, mit dessen Hilfe für die Quellcode der einzelnen Erweiterungen ein configure-Skript erstellt wird, während php-config alle wichtigen Pfadangaben und Optionen für das Kompilieren enthält. Die Quellen der einzelnen Erweiterungen finden sich in dem Archivextrakt unterhalb des Verzeichnisses ext/. Wechseln Sie in dieses Verzeichnis und sehen Sie sich an, welche Erweiterung im Quellcode von Hause aus enthalten sind:
Weitere Erweiterungen können von pecl.php.net oder anderen Anbietern bezogen werden. Die Vorgehensweise ist dabei stets dieselbe.
Erstellen sie nun ihr erstes PHP-Modul für Perl-kompatible Reguläre Ausdrücke:
Dabei wird ihnen folgende Fehlermeldung ausgegeben:
Daher habe ich Sie mit dieser Erweiterung anfangen lassen. Einige Erweiterungen haben ihre config-Anweisungen unter dem Namen config0.m4 oder auch config.m4.0 abgelegt. Sehen Sie sich also bei solchen Fehlermeldungen den Inhalt des Verzeichnis an und kopieren Sie die entsprechende Datei, sodass sie von phpize gefunden wird:
Nehmen Sie sich nun eine andere Erweiterung als zusammenhängendes Beispiel vor:

### Tipps und Tricks

Fehler beim Kompilieren vermeiden
Es kann öfters mal etwas schief gehen: C-Headerdateien für bestimmte Erweiterungen sind nicht vorhanden, make bricht ab, oder Sie stellen nach dem Kompilieren ganz einfach fest, dass Sie dem configure-Skript nicht alle gewünschten Optionen übergeben haben. Für gewöhnlich ruft man make clean an der Konsole auf. Jedoch gab es in der Vergangenheit damit immer wieder Probleme.
Daher sollten Sie den extrahierten Quellcode komplett löschen, neu entpacken und von vorn beginnen.
Zlib muss mit!
Wenn Sie PHP für Webprojekte neu aufsetzen, wählen Sie unbedingt die Option --with-zlib. Sie können sich so eine Menge an Bandbreite sparen. Lesen Sie näheres unter Konfiguration.
atomares Datei-Locking sicherstellen
Da auf Multithreaded Server mit z. B. flock nicht sichergestellt werden kann, dass Dateien exklusiv für einen einzelnen Vorgang gesperrt werden, aktivieren Sie die Erweiterung Semaphoren mit --enable-sysvsem. Mit Hilfe dieser Erweiterung können Sie sich ein atomares Datei-Locking erstellen.
Optionen übergeben
Anders als bei anderem Quellcode bietet PHP keine direkten Möglichkeiten, dem configure-Skript Optionen für das Kompilieren zu übergeben. Gehen Sie daher folgendermaßen vor:
Ober bestimmen Sie breits beim Kompilieren, wo Sie Ihre Include-Dateien abgelegt haben oder Ihr Verzeichnis für die PHP-Module angelegt werden soll:
Vereinfachungen
Legen Sie sich ein wiederverwendbare Konfigurationsdatei an und führen Sie diese von Version zu Version aus:
Eine Beispielkonfigurationsdatei:

# Anpassen der Apache-Konfiguration
## Konfiguration für CGI

Nehmen sie in die Apache-Konfigurationsdateien (httpd.conf/.htaccess) folgende Direktiven auf:
Die grünen Passage können sie nennen, wie sie wollen. Wichtig ist nur, dass ihnen der Zusammenhang zwischen der Angabe des ScriptAlias und der Action-Direktive klar ist. Unter Windows sieht das z. B. dann so aus:

## Konfiguration für mod_php

Nehmen sie folgende Zeilen in ihre httpd.conf auf, wenn diese noch nicht vorhanden sind:
Für Windows notieren sie bitte eine der folgenden Zeilen (Je nach Version Apaches und PHP):

## Skripte durch Endungen erkennen

Es gibt mehrere Möglichkeiten den Apachen zu konfigurieren, damit er PHP-Skripte ausführt. Diese Angaben treffen sowohl auf PHP als Servermodul, wie auch auf das CGI-Binär zu. Nehmen sie folgende Zeilen in die mime.conf auf:
Darüber hinaus können sie Verzeichnisweit (.htaccess) mit der Direktive AddType arbeiten:
Hinweis: Sie werden PHP nicht zum Laufen bekommen, wenn sie vergessen haben mod_mime (für CGI darüber hinaus mod_alias) in den Server zu kompilieren, oder diese(s) nicht aktiviert haben!

# Verweise

Unter den folgenden Verweisen bekommen sie weitergehende Hilfestellungen und Alternativen zur PHP-Installation:
* Installations-FAQ des Handbuches (Hilfreiche Zusammenstellungen von Problemen während der Installation und Lösungswege)
* Anleitung zum Betrieb von PHP als FastCGI (Detaillierte Beschreibung einer Installation von Apache 2.x und FastCGI unter Debian)
* suphp.org (Quellcode und Beschreibung für die Installation von mod_suphp. Es ermöglicht das Ändern von Benutzer und Gruppe vor der Skriptausführung unter Apache.)
* Apache-Konfigurationsdatei - Serverseitige Techniken (Ein Artikel, der die Konfiguration Apaches mit PHP beschreibt.)
* Apache2-PHP-MySQL-Wiki für Gentoo (Ein HowTo für die Installation von Apache, PHP und MySQL unter Gentoo)
* PHP Accelerator (Entwickler-Website von PHP Accelerator, einer kostenlosen Zend-Erweiterung zur Beschleunigung der Ausführung von PHP.)
* SecurePHP (Ein englischsprachiges Wiki rund um die Sicherheit von PHP.)
* >e-novative> WAMP Kostenloses Installationsprogramm für PHP, Apache, MySql und phpMyAdmin unter Windows
* Apachefriends (xampp - eine LAMP-TEST-Entwicklungsumgebung von Apachefriends, gut für Einsteiger, mit Downloadmöglichkeit und anderen nützlichen Tipps und Tricks)
* xampp (Downloadmöglichkeit bei sourceforge.net)

# Abschließende Bemerkung

Der Apache-Server muss für jede Änderung der Konfiguration neu gestartet werden. Wird PHP als Servermodul genutzt, gilt dies auch für Anpassungen in der php.ini!
Diese Bemerkung ist deswegen notwendig, da die meisten Fragesteller in Foren bei Problemen rund um die PHP-Konfiguration dies nicht beherzigt haben.

# Konfiguration

Websiteentwicklung PHP Konfiguration

# Grundlegendes

Nehmen Sie sich die Zeit, PHP sorgfältig zu konfigurieren! Da PHP eine sehr mächtige Skriptsprache ist, die sehr viele Dinge kann, kann sie – (z. B.) falsch konfiguriert – auch sehr viel kaputtmachen. Das soll Sie nur warnen und nicht gleich verschrecken. ;)
Die Konfiguration von PHP wird über Direktiven gesteuert. Diese lassen sich in drei Gruppen einteilen, die durch die Konstanten PHP_INI_ALL, PHP_INI_PERDIR und PHP_INI_SYSTEM des Quellcodes bestimmt werden.

## PHP_INI_ALL

    Ist eine PHP-Direktive mit dieser Konstante implementiert worden, kann sie in Skripten (z. B. durch ini_set), in der php.ini und den Konfigurationsdateien httpd.conf und .htaccess geändert werden.

## PHP_INI_PERDIR

    Ist eine PHP-Direktive mit dieser Konstante implementiert worden, kann sie nicht in Skripten geändert werden, sondern nur in der php.ini und den Konfigurationsdateien httpd.conf und .htaccess.

## PHP_INI_SYSTEM

    Ist eine PHP-Direktive mit dieser Konstante implementiert worden, kann sie ausschließlich in der php.ini und der httpd.conf geändert werden.

# Die Konfigurationsdatei php.ini

Die php.ini ist die zentrale Konfigurationsdatei durch die alle Verhaltensregeln von PHP festgelegt werden. Innerhalb des Quellcodes werden zwei verschiedene Konfigurationsdateien mitgeliefert. Das ist zum einen die php.ini-dist und zum anderen die php.ini-recommended. Sie sind gut kommentiert – allerdings nur für jemanden der sich bereits auskennt. Daher sollten sie dieses Kapitel gründlich lesen, damit auch Sie sich auskennen werden.
Manche Einstellung, die Sie in der php.ini vornehmen können, kann Ihnen Arbeit beim Programmieren abnehmen. Sie sollten sich also immer vergewissern, ob es für ein Problem, welches Sie beim Programmieren feststellen und lösen wollen, nur eines einfachen Handgriffs in der Konfiguration bedarf. Sie sollten aber auch bedenken, dass gesetzte Direktiven innerhalb der php.ini systemweite Wirkung entfalten (können). Daher ist es ratsam, hier in Abwägung des mehrheitlichen Nutzen aller Skripte zu konfigurieren.
Kontrollieren Sie Ihre Konfiguration mit der Funktion phpinfo (oder mit dem Parameter -i, wenn Sie mit dem CLI an der Kommandozeile arbeiten). phpinfo gibt Ihnen alle erheblichen System-, Server-, Umgebungsvariablen- und Konfigurationangaben aus:
Hinweis: Das PHP-Komandozeilenprogramm (CLI) parst nur Dateien mit Namen php-cli.ini.

## Syntax

Die Syntax der php.ini gestaltet sich erfreulich übersichtlich:

### Direktiven

    Direktiven bestehen aus dem Paar Name und Wert, die durch ein Gleichheitszeichen "=" voneinander getrennt werden. asp_tags=Off Lesen Sie mehr zu den einzelnen Direktiven unter Alphabetische Liste der Direktiven.

### Kommentare

    Ein Kommentar beginnt mit ein Semikolon ";". Er endet mit dem Zeilenende. Zeilenübergreifende Kommentare gibt es in PHP nicht.Direktive=Wert ; Kommentar

### Sektionen

    Sektionen werden durch einen Text umschlossen von einem Paar Eckiger Klammern ("[" und "]") festgelegt. Sie entfalten für die Steuerung von PHP keinerlei Wirkung und sind nur für die Ausgabe der Funktion parse_ini_file von Bedeutung. [Sektion_1]

### Variablen

    Alle Direktiven können als Variable innerhalb der php.ini eingesetzt werden. Ein Variable setzt sich aus dem Dollarzeichen "$" gefolgt vom in einem Paar Geschweifter Klammern ("{" und "}") notierten Direktivennamen, dessen Inhalt verwendet werden soll. Diese Möglichkeit steht Ihnen erst seit der Version 5.1 zur Verfügung.open_basedir=${include_path}":/ein/anderer/pfad"

## Wohin muss die php.ini

Hinweis: Wurde PHP als Apache-Modul (Version 1.3.x) unter der configure-Option des Apachen --activate-module installiert, werden keinerlei Einstellungen der php.ini beachtet. Sie können PHP in diesem Fall nur über die Konfigurationsdateien des Apachen abstimmen. Lesen sie dazu mehr im nächsten Abschnitt Konfiguration unter Apache.
Die Verzeichnisse, unter denen PHP vor der Ausführung von Skripten nach Konfigurationen sucht, werden dem configure-Skript mit den Optionen --with-config-file-path und --with-config-file-scan-dir mitgeteilt und sind nach dem Kompilieren nicht mehr veränderbar. Wenn Sie also wissen wollen, wo Sie Ihre php.ini ablegen müssen, führen Sie folgendes Skript aus und suchen Sie die entsprechenden Optionen in den Spalte für Configure Command und Configuration File:
Eine mögliche Ausgabe könnte so aussehen:
| System | Linux eddi.to-grip.de 2.6.16.9 #1 Tue Apr 19 12:00:01 CEST 2006 x86_64 |
| Build Date | Jan 19 2006 04:16:00 |
| Configure Command | './configure' '--disable-all' '--disable-short-tags' '--enable-memory-limit' '--enable-sysvsem' '--enable-sysvshm' '--with-apxs2=/usr/local/apache/bin/apxs' '--with-bz2' '--with-config-file-path=/etc' '--with-openssl' '--with-zend-vm=GOTO' '--with-zlib' |
| Server API | Apache 2.0 Handler |
| Virtual Directory Support | enabled |
| Configuration File (php.ini) Path | /etc/php.ini |
| PHP API | 20041225 |
| PHP Extension | 20050922 |
| Zend Extension | 220051025 |
| Debug Build | no |
| Thread Safety | enabled |
| Zend Memory Manager | enabled |
| IPv6 Support | enabled |
| Registered PHP Streams | php, file, http, ftp, compress.bzip2, compress.zlib, https, ftps |
| Registered Stream Socket Transports | tcp, udp, unix, udg, ssl, sslv3, sslv2, tls |
| Registered Stream Filters | string.rot13, string.toupper, string.tolower, string.strip_tags, convert.*, consumed, bzip2.*, zlib.* |
Hinweis: Die Konfiguration der Direktive expose_php lässt sich ausschließlich in der php.ini vornehmen.

# Konfiguration unter Apache

Um PHP durch die Serverkonfigurationsdateien (httpd.conf/.htaccess) steuern zu können, muss PHP als Servermodul installiert sein. Wenn Sie sich nicht sicher sind, mit welchem SAPI Sie es zu tun haben, führen Sie folgendes Skript aus:
Mögliche Ausgaben dieses Skripts sind dabei cgi, cgi-fcgi, apache2handler, apache2filter oder apache. Folgende Beschreibung gilt also nur für die letzten drei SAPIs. Für die Konfiguration der CGI-Binäre lesen Sie bitte Apache: PHP als CGI.

## PHP als Webservermodul

Als Apache-Modul setzt PHP einige Konfigurationsdirektiven, die Ihnen im folgenden erklärt werden:

### php_value name value

    Setzt den angegebenen Wert value für die mit name angegebene PHP-Direktive. Diese Direktive kann in allen Konfigurationsdateien (httpd.conf/.htaccess) des Apachen für die Steuerung von PHP-Direktiven verwendet werden, den Wertetyp string oder integer haben, und deren Änderbarkeit auf PHP_INI_ALL | PHP_INI_PERDIR gesetzt ist.

### php_flag name on/off

    Setzt den angegebenen Wert value für die mit name angegebene PHP-Direktive. Diese Direktive kann in allen Konfigurationsdateien (httpd.conf/.htaccess) des Apachen für die Steuerung von PHP-Direktiven verwendet werden, den Wertetyp boolean haben, und deren Änderbarkeit auf PHP_INI_ALL | PHP_INI_PERDIR gesetzt ist.

### php_admin_value name value

    Setzt den angegebenen Wert value für die mit name angegebene PHP-Direktive, sodass dieser sich nicht mehr mit Angaben in .htaccess-Dateien überschreiben lässt. Diese Direktive kann in der zentralen Konfiguration (httpd.conf) des Apachen für die Steuerung von PHP-Direktiven verwendet werden, den Wertetyp string oder integer haben, und deren Änderbarkeit auf PHP_INI_ALL | PHP_INI_PERDIR | PHP_INI_SYSTEM gesetzt ist.

### php_admin_flag name name on/off

    Setzt den angegebenen Wert value für die mit name angegebene PHP-Direktive, sodass dieser sich nicht mehr mit Angaben in .htaccess-Dateien überschreiben lässt. Diese Direktive kann in der zentralen Konfiguration (httpd.conf) des Apachen für die Steuerung von PHP-Direktiven verwendet werden, den Wertetyp boolean haben, und deren Änderbarkeit auf PHP_INI_ALL | PHP_INI_PERDIR | PHP_INI_SYSTEM gesetzt ist.
Ein Beispiel für die Konfiguration eines Virtual-Hosts:

## PHP als CGI

Die CGI-Binäre von PHP werden über die php.ini konfiguriert, daher werden Ihnen in diesem Abschnitt nur Tricks vorgestellt, wie Sie spezielle Konfigurationen umsetzen können.
Bis vor einigen Jahren suchte PHP im jeweiligen Skript-Verzeichnis nach einer Konfigurationsdatei. Leider ist diese überaus praktische Funktionalität in neueren Versionen aus Sicherheitsgründen nicht mehr umgesetzt worden. Dafür kann PHP auf Kommandozeilenebene mit einem Parameter -c aufgerufen werden, der als Argument den Pfad zu einer php.ini bzw. zu einem Verzeichnis erwartet.
Also erstellen Sie sich ein kleines Shell-Skript, dass PHP mit einer Konfigurationsdateiangabe aufrufen kann:
Dieses Shell-Skript wird im Verzeichnis des PHP-Skriptes nach der Datei php.ini suchen. Ist keine php.ini in diesem Verzeichnis, wird PHP mit einer Default-Konfigurationsdatei (/pfad/zur/default_ini/php.ini) gestartet. Passen Sie die Pfandangaben an Ihre Gegebenheiten an und legen Sie dieses Shell-Skript in das Verzeichnis des CGI-Binärs ab. Ich habe das Skript startphp.sh genannt.
Als nächstes muss die Konfiguration des Apachen geändert werden, damit PHP nicht mehr direkt aufgerufen wird, sondern das Shell-Skript dieses erledigt:
Nach einem Restart des Webservers wird PHP sodann mit der verzeichnisweiten (oder eben mit der default) Konfigurationen gestartet. Insbesondere für Anwendungsentwickler erweist sich diese Vorgehensweise als nützlich. Sie können so an einem lokalen Testserver die jeweiligen Konfigurationen (und auch den entsprechenden PHP-Versionen) verschiedener Produktivumgebungen simulieren.
Wenn Sie selbst Webdienste anbieten, ist dieses Skript natürlich nicht für den Einsatz geeignet, da Sie sonst keine Funktionen sperren und andere wirksame Sicherheitsmaßnahmen mehr treffen können. Aber mit einem leicht modifizierten Skript wird es Ihnen möglich, jedem Web eine individuelle Konfiguration zu verpassen.
Wie bereits im ersten Skript nutzen Sie dazu eine Umgebungsvariable. Da jedes Web die serverweit eindeutige Variable SERVER_NAME hat, können Sie diese zur Identifikation nutzen. Für alle Webprojekte, denen Sie also eine individuelle Konfiguration zukommen lassen wollen, erstellen Sie in einem Verzeichnis eine eigene Konfigurationsdatei; für alle anderen Webprojekte wird PHP mit default-Konfigurationen gestartet:
Die Konfigurationsdatei für den Virtualhost localhost heißt also localhost.ini.

# Konfiguration innerhalb von Skripten

Die Möglichkeit, PHP innerhalb von Skripten zu konfigurieren, gehört zu den häufig genutzten. Sie können Ihre Skripte dadurch portabel machen, ohne Einstellungen in Konfigurationsdateien, wie der php.ini, vornehmen zu müssen. Jedoch lassen sich nicht alle Direktiven manipulieren. Unter Konfiguration Grundlegendens wurde Ihnen kurz dargelegt, welche drei Kategorien von Direktiven es gibt. Innerhalb von Skripten können Sie nur Direktiven ändern, deren Änderbarkeit durch die Konstante PHP_INI_ALL repräsentiert wird.
Die beiden folgenden Skripte sind im Resultat analog zueinander:
Es wird in beiden Fällen ein HTTP-Header Content-Type gesendet. Auch wenn dies ein schlechtes Beispiel ist, weil diese Konfiguration verzeichnisweit für einen Webauftritt in Konfigurationsdateien gesetzt werden sollte, zeigt Ihnen das zweite Skript die Funktion ini_set. ini_set ist die wichtigste Funktion, um innerhalb von Skripten Konfigurationen zu manipulieren.
Beachten Sie im Umgang mit ini_set, das es unterschiedliche Typen von Direktiven gibt. Die Typen sind boolean, integer und string und verhalten sich wie die gleichnamigen Variablentypen:
Darüber hinaus gibt es noch eine Vielzahl von Funktionen, die eine ganz bestimmte Direktive manipulieren. Wenn Sie diese kennenlernen wollen, sehen Sie sich dazu die Kommentare in der Alphabetische Liste der Direktiven an.

# Themenweite Konfiguration

in Bearbeitung!

## Der abgesicherte Modus

in Bearbeitung!

## Dateien hochladen

in Bearbeitung!

## Datenkompression für Webserver

Das Hypertexttransfer Protokoll (HTTP 1.1 RFC 2616) bietet die Möglichkeit Daten auch komprimiert auszuliefern. Ein Client (z. B. Ihr Browser) sendet dazu an einen Server im Anfrageheader Informationen, dass er auch komprimierte Daten akzeptiert und welche Kompressionsverfahren er unterstützt. Gerade zur Sicherung der Bandbreite eines Webservers ist die komprimierte Auslieferung wichtig. PHP sollte daher für Webserver immer mit dem zlib-Modul kompiliert werden. Ist PHP mit diesem Modul übersetzt worden, sollten sie dieses Modul auch nutzen!
Konfiguration in der php.ini:
oder Konfiguration am Anfang eines jeden Skripts:
PHP wird dadurch veranlaßt, einen internen Ausgabepuffer einzusetzen (die Skriptausgaben aber auch Daten außerhalb der Skriptblöcke werden zwischengespeichert) und nach Beendigung der Skriptausführung die Ausgabe gegebenenfalls zu komprimieren.

## PHP auf dem Webserver verschleiern

Es kann viel Gründe dafür geben, die Existenz von PHP auf einem Webserver zu verschleiern. Wenn Sie schon einmal nach einer Fertiglösung in Suchmaschinen suchten, die Sie in PHP haben wollten, werden Sie bereits einen guten Grund kennen. Manche Suchmaschinen neigen dazu auch die URL für Ihr Suchmuster als Treffer heranzuziehen und es wird Ihnen ein Haufen belangloser Verweise angeboten, nur weil diese auf .php enden.
Seit 2005 hatten sich auch einige sogenannte "Linux-Würmer" darauf spezialisiert, Suchmaschinen gezielt nach schlecht geschriebenen Skripten zu durchsuchen, um sich zu vermehren. Daher kann das Verschleiern auch ein wenig mehr Sicherheit bringen.
Für einen Besucher einer Internetpräsenz ist natürlich die Dateiendung .php ein deutliches Zeichen auf die eingesetzte Technik. Aber genaugenommen braucht kein Mensch die Dateiendungen, um durch Inhalte zu browsen. Daher ist eine URL der Form www.domain.de/verzeichnis/datei genauso aussagekräftig, wie www.domain.de/verzeichnis/datei.php. Nehmen Sie dazu in Ihre Apache-Konfiguration folgendes auf:
Dies wird mod_negotiation für die Abarbeitung eines Requests auf den Plan rufen. Sollte dieses Modul nicht in den Webserver einkompiliert oder geladen worden sein, können Sie nur die Dateiendungen abändern:
Natürlich können Sie auch mod_rewrite nutzen oder sich des unter Pseudo-URLs durch PATH_INFO gezeigten Tricks bedienen.
Sollten Sie aus sicherheitstaktischen Gründen PHP verschleiern wollen, so seien Sie hiermit gewarnt. Es reicht nicht aus, nur die Dateiendungen zu verbergen. Die Anwesenheit von PHP schlägt sich auch in HTTP-Headern nieder. So erzeugt die erste Beispielkonfiguration folgende Header:
Die Header Content-Location, TCN und Vary rühren dabei vom mod_negotiation. X-Powered-By und der Anhang im Server-Header kommen aber von PHP selbst. Diese können durch die Direktive expose_php in der php.ini deaktiviert werden.

## Pseudo-URLs durch PATH_INFO

Die hier vermittelten Informationen fordern von Ihnen schon gefestigte Kenntnisse im Umgang mit PHP. Wenn Sie mit PHP beginnen wollen und dieses Wikibook in chronologischer Reihenfolge lesen, wird Sie dieser Abschnitt überfordern. Sie werden noch an einigen Stellen dieses Wikibooks auf Informationen stoßen, die Sie nicht auf Anhieb verstehen werden. Lassen Sie sich davon nicht beirren, sondern kehren Sie mit dem später erworbenen Wissen an diese Stellen wieder zurück!
Dieser Abschnitt könnte auch die Überschrift Machen Sie mod_rewrite arbeitslos haben. mod_rewrite ist ein beliebtes Apache-Modul, das Anfragen an Ressourcen umformulieren kann. Dadurch ist es möglich Pseudolinks in einem Webprojekt einzubetten, die es reell gar nicht gibt. Nur wer braucht schon dieses Modul, wenn er bereits PHP hat? ;)
Legen Sie also eine .htaccess in das oberste Web-Verzeichnis mit folgendem Inhalt:
Diese Konfiguration wird den Apache veranlassen die Datei meinwiki wie ein PHP-Skript zu behandeln. Erstellen Sie nun das Skript meinwiki:
Sie können aber auch die Pfadangaben, wie mod_rewrite es tun würde, in Variablen zerlegen:
Dieses entspricht folgender Rewrite-Regel:
Somit kommen auch Nutzer des IIS in den Genuß einer Rewriteengine.

# Grundlagen

Websiteentwicklung PHP Grundlagen
PHP-Scripte sind reine Textdateien (auch plaintext genannt), die mit jedem einfachen Text-Editor-Programm erstellt werden können. Die Scripte müssen jedoch eine bestimmte Endung (Erweiterung oder auch Extension) aufweisen, um vom Webserver als solche erkannt zu werden. Welche Endungen das sind, ist nicht festgelegt und kann über den Webserver konfiguriert werden. Üblich sind die Erweiterungen .php, .phtml, .php4 oder auch .php5. Oft benutzt man die Versionsnamen als Endung, wenn auf dem Server aus Kompatibilitätsgründen zwei (z.B. PHP 4 & 5) PHP Versionen installiert sind und diese dann durch die Endung unterschieden werden. Die Endung .php ist hierbei zu empfehlen, da sie am weitesten verbreitet ist.

## PHP Tags

Ein PHP-Block wird mit folgenden Tags geöffnet und wieder geschlossen:
* <?php ... ?>
Der PHP-Parser erkennt diese Tags und arbeitet die PHP-Befehle zwischen diesen Tags ab. Man sollte diese Form benutzen, da sie von allen Servern interpretiert werden kann. Außerdem ist die Schreibweise <?php ... ?> XML-konform und schon aus diesem Grund zu empfehlen.
Daneben existieren weitere Möglichkeiten, die teilweise von Einstellungen in der PHP-Installation abhängen:
* <script language="php"> ... </script>
* <? ... ?> (Abhängig von.. short-open-tags)
* <?= ... ?> als eine Kurzform von <? echo ...; ?> (Abhängig von.. short-open-tags)
* <% ... %> (Abhängig von.. asp-tags)
* <%= ... %> als eine Kurzform von <% echo ...; ?> (Abhängig von.. asp-tags)

### Hallo Welt, eine Beispieldatei

Eine Beispieldatei könnte so aussehen:
Ausgabe:
So sieht ein Script in einer reinen PHP-Datei aus. Der Befehl echo gibt den Text der in doppelten oder einfachen Anführungszeichen angegeben ist aus. Eine Anweisung (wie echo) wird mit einem Semikolon am Ende der Zeile beendet.

## PHP und HTML in einer Datei

Ein PHP-Script wird oft in eine HTML-Datei eingebunden. Das heißt irgendwo in der Datei kann ein PHP-Block geöffnet und wieder geschlossen werden. Bevor der Webserver die HTML-Datei ausliefert, reicht er sie an den PHP-Parser weiter, der dann die PHP-Blöcke abarbeitet.
Beispiel:
Ausgabe im Browser (für den Benutzer sichtbar):
Obwohl der PHP-Code innerhalb eines HTML-Codes steht, muss die Datei auf .php enden, damit der Parser auch die Datei bzw. den PHP-Code in dieser Datei abarbeitet, wobei das von den Einstellungen des Servers abhängig ist. So kann man auch erzwingen, dass eine Datei geparst wird, die z.B. auf .html endet, selbst wenn sie keinen PHP-Code enthält.

## Header und Content

Beim Aufruf einer Internetseite bekommt der Browser (bzw. ein ähnliches Programm, das mit HTTP arbeitet) zwei Teile zugesandt. Einmal ist das der Header und einmal der Content.

### Header

Die Daten, die in diesem Bereich stehen, beschreiben den folgenden Content. Hier sind Informationen wie Dateigröße und Dateityp hinterlegt. Teile des Headers könnten wie folgt aussehen:

### Content

Hier befindet sich der eigentliche Inhalt, mit dem der Browser arbeitet. Je nach den Daten in den Headern führt der Browser eine entsprechende Aktion aus. HTML-Daten werden interpretiert, Bild-Daten werden angezeigt, ZIP-Daten werden gespeichert...
Mit PHP ist es möglich beide Teile zu verändern, wenn dies denn Sinn hat. Dabei muss man die Reihenfolge beachten, in der man diese Teile verändert. Man darf die Headerangaben nur dann verändern, wenn man noch keinen Inhalt/Content erzeugt hat. Dies ist z.B. bei Cookies wichtig, da Cookies Headerangaben sind. Oder auch, wenn man mit PHP Bilder erzeugen möchte. Auch HTML-Code gehört zum Content. Wenn also außerhalb von PHP HTML-Code ausgegeben wird (weil z. B. PHP in HTML-Code eingebettet wurde) ist es nicht mehr möglich den Headerteil zu verändern. Dies wird spätestens anhand der Fehlermeldung Warning: Cannot add header information - headers already sent ... deutlich.

# Ausgabe

Websiteentwicklung PHP Ausgabe

## Das erste "Hello World!"

Das folgende Script gibt den Text Hello World aus. Dazu erstellen Sie eine neue Datei namens helloworld.php in ihrem PHP-fähigen Webspace. Die folgenden drei Zeilen sind der Inhalt dieser einfachen Datei:
Rufen sie nun die Datei über ihren Web-Browser auf. Je nachdem wo sie die Datei gespeichert haben (Webserver oder lokaler virtueller Server) geben sie ähnlichlautende URL's ein: http://ich.meinhoster.de/helloworld.php http://localhost/helloworld.php Jetzt sehen Sie auf Ihrem Bildschirm

## Strings (Zeichenketten)

Betrachten wir eine Zeile des Beispiels einmal genauer:
Hello World ist offensichtlich der Text, der auf dem Bildschirm ausgegeben wird.
echo ist unser erster PHP-Befehl, genauer gesagt ein Sprachkonstrukt. Mit echo ist es möglich, einen String (engl. für Zeichenkette) anzuzeigen.

### Semikolon

Ein PHP-Befehl wird mit einem Semikolon ; beendet.
Es ist ein häufiger Anfängerfehler, das Semikolon zu vergessen.

### Single-Quotes

Der Text des Strings muss in "Single-Quotes" '...' eingeschlossen sein.

### Double-Quotes

Genausogut kann man Strings mit Anführungszeichen "..." deklarieren:

### Zeichen "escapen"

Bestimmte Zeichen besitzen besondere Aufgaben in einem String, wie zum Beispiel das Markieren einer Variable ($) in Double-Quotes (siehe unten). Falls man das Zeichen allerdings selbst braucht (um z.B. einen Dollar Betrag auszugeben) dann muss man das gewünschte Zeichen "escapen", d.h. es mit dem Prefix '\' versehen damit PHP weiß, dass dieses Zeichen an sich ausgegeben werden soll und es nicht vom Parser geparst wird.
So muss zum Beispiel innerhalb eines Single-Quotes das Single-Quote (') escaped werden, da es sonst als Ende des Strings ausgewertet werden müsste. Das gleiche gilt ebenfalls für die Double-Quotes. Um nun das Escape-Zeichen (auch Backslash genannt) selbst darzustellen, muss es ebenfalls escaped werden (\\).
PHP interpretiert eine Escape-Kette, die keine Bedeutung besitzt nicht, so dass dann ebenfalls das Escape-Zeichen mit ausgegeben wird.

### Heredoc

Heredoc arbeitet über Bezeichner und die Kette "<<<". Systematisch arbeitet es wie die Double-Quotes, nur dass es keine doppelten Anführungszeichen besitzt und diese nicht im Text escaped werden müssen. Es dürfen aber alle Escape-Regeln verwendet werden. Die Heredoc-Ausgabe wird mit "<<<" und einem eindeutigen Bezeichner eingeleitet, der am Ende des Strings, der ausgegeben werden soll, die Zeichenkette wieder schließt
Wie man sieht, ist auch eine Ausgabe über mehrere Zeilen problemlos möglich. Wichtig ist, dass der beendende Bezeichner in seiner Zeile nur sich selbst und ein ";" besitzen darf, also auch keine Einrückungen oder sonstiges. Ansonsten würde PHP den Bezeichner nicht finden und einen Fehler am Ende des Scripts ausgeben, dass der Bezeichner nicht gefunden wurde.

## Ausgabe mit print und echo

Wie du in den Beispielen davor schon gesehen hast kann man mit echo '...'; bzw. echo "..."; Zeichenketten oder Variablen ausgeben. print '...'; macht genau das selbe, liefert jedoch immer 1 als Rückgabewert zurück, das braucht dich allerdings im Moment nicht zu interessieren. Ob nun echo oder print ist letztendlich aus der technischen Sicht egal. Da echo allerdings verbreiteter ist, bietet es sich an, echo zu benutzen.

## Übungen

Nun bist du an der Reihe. Versuche diese Aufgaben zu lösen - aber probiere nicht nach oben zu schauen ;-).
* Programmiere mit PHP ein Skript, welches den Text "Hallo. Morgen geht die Sonne auf." ausgibt

# Kommentare

Websiteentwicklung PHP Kommentare
Kommentare sind Teile eines PHP-Skriptes, die vom PHP-Parser ignoriert und daher nicht ausgeführt werden. Somit ist es möglich, Anmerkungen und Notizen zu einem Skript und Erläuterungen zum Code hinzuzufügen. Die Lesbarkeit des Codes wird dadurch erhöht, sowohl für andere Personen als auch für den Autor selbst.
In PHP gibt es verschiedene Arten von Kommentaren: einzeilige, mehrzeilige und PHPDoc-Kommentare.

## Einzeilige Kommentare

Einzeilige Kommentare reichen nur bis zum Ende der Zeile. Sie werden mit // eingeleitet. Alternativ, aber seltener gebraucht, mit Hilfe von #. Alles was in der gleichen Zeile im Anschluss folgt wird vom PHP-Parser ignoriert. Beispiel:

## Mehrzeilige Kommentare

Mehrzeilige Kommentare können über mehrere Zeilen verlaufen - und zwar so lange, bis sie beendet werden. Ähnlich wie in XHTML gibt es für einen mehrzeiligen Kommentar eine "Startsquenz" und eine "Schlusssequenz". Ein mehrzeiliger Kommentar beginnt mit /* und geht bis zum nächsten */.

## Auskommentieren

Mit Hilfe der Kommentare ist es möglich einzelne Anweisungen oder ganze Anweisungsgruppen von der Ausführung durch den PHP-Interpreter auszunehmen, ohne sie aus dem Script zu löschen.
Das Auskommentieren von einzelnen Zeilen oder ganzen Abschnitten wird häufig bei der Fehlersuche verwendet. So kann man beispielsweise Funktionen oder ganze Programmabschnitte von denen man vermutet, dass sie einen Fehler verursachen, als Kommentar kennzeichnen. Führt man das Script nun erneut aus und der Fehler tritt nicht mehr auf, so weiß man dass der Fehler in der Funktion bzw. in diesem Programmabschnitt vorhanden sein muss. Damit ist es für den Programmierer leicht möglich, den fehlerhaften Bereich zu lokalisieren.

## PHPDoc-Kommentare

PHPDoc-Kommentare können dazu genutzt werden, die Erstellung einer Dokumentation zu vereinfachen. Gestartet werden sie mit /**, jede neue Zeile wird durch einen Stern eingeleitet. Beendet werden sie mit */. Diese Art der Kommentare braucht dich im Moment noch nicht zu interessieren, da diese oft nur bei komplexerem und umfangreicherem Code benutzt werden.
Beispiel:

# Variablen

Websiteentwicklung PHP Variablen
Bis jetzt war jeder Text, den wir auf dem Bildschirm ausgegeben haben, statisch. Das heißt, wir haben den Text, den wir ausgeben wollen, in einer PHP Datei gespeichert und dann mittels echo anzeigen lassen:
Allerdings soll ein Nutzer die Möglichkeit haben, mit einem Skript zu interagieren. Dafür brauchen wir Variablen. Eine Variablen dient als Speicherort (bzw. Zeiger zu Speicherorten im RAM) für Informationen. Variablen werden in PHP immer mit einem Dollarzeichen ($) vor dem Variablennamen gekennzeichnet.

## Variablentypen

Anders als in anderen Programmiersprachen wie Pascal oder C++ muss in PHP nicht der Typ einer Variable definiert werden (z.B. int für eine Zahl oder String für einen Text) da PHP eine sogenannte Typ-schwache Programmiersprache ist.
Auch wenn PHP, wie schon gesagt, eine Typ-schwache Programmiersprache ist, heißt dies nicht, dass die Variablen keinen Typ haben, sondern dass der PHP-Interpreter die Typen der Variablen selbst festlegt. Dies macht es einerseits für Anfänger leichter, da diese sich keine Variablentypen merken müssen, andererseits führt es aber auch dazu, dass Variablentypen aus Versehen geändert werden können und der Programmierer nichts davon merkt. Generell sollte man den Typen einer Variable zur Laufzeit (also im Quellcode) nicht ändern, sondern notfalls eine neue Variable anlegen, welche die alte Variable beinhaltet aber vom anderen Typ ist.

### Typen

Auch wenn du selbst keine Variablentypen festlegst ist es notwendig, dass du weißt welche Typen die einzelnen Variablen haben. Variablen in einem PHP-Script können einen der folgenden Typen haben:

#### Normale Typen

string, Zeichenketten Ein String besteht aus einer Kette von Zeichen, also einem Wort, einem Satz, einem Buchstaben, einem Text oder auch dem ganzen HTML-Quellcode (der ja auch nur eine Reihe/Kette von Zeichen ist). $var_str = 'Text';
integer, Ganzzahl Ein Integer ist eine normale Zahl die zwischen -2147483648 und +2147483647, diese Zahl kann keine Kommastellen haben. Bitte beachte, dass Integer ohne Anführungszeichen angegeben werden. $var_int = 12;
float/double, Fließkomma-Zahl Ein Float (oder auch double genannt, beide Typen sind allerdings in PHP gleich) ist eine Zahl mit Kommastellen. Das Komma wird bei den Programmiersprachen (die alle "Englisch" sind) allerdings zu einem Punkt. $var_float = 12.12;
boolean, Wahrheitswert Boolean ist ein Variablentyp mit zwei einfachen Werten, richtig oder falsch (true und false). Booleans werden in Bedingungen benutzt, alle Vergleichsoperatoren (mehr dazu im nächsten Kapitel) geben einen Boolean zurück. $var_bool = true;

#### Zusammengesetzte Typen

array, Datenbereich Ein Array ist eine Gruppierung von einzelnen Variablen zu einer großen, mehr dazu im Kapitel Arrays.
object, Objekt Ein Objekt wird in der objektorientierten Programmierung benutzt, mehr dazu im Kapitel OOP (Objekt Orientierte Programmierung).

#### Spezialtypen

resource Jedes mal, wenn man mit Systemressourcen, wie zum Beispiel Dateien, arbeitet, kommt man mit Variablen des Types resource in Verbindung. Diese Variablen beinhalten immer nur "Zeiger" zu den Systemressourcen und können nur von entsprechenden PHP-Funktionen verarbeitet werden.
NULL Dies ist sozusagen der Standardwert einer jeden Variable. Jede uninitialisierte (also noch nicht zugewiesene) Variable besitzt diesen Typ, man kann ihn allerdings auch durch eine Zuweisung auf NULL ($var = NULL;) oder durch die Benutzung der Funktion unset nachstellen.

## Initialisierung

In PHP müssen Variablen nicht notwendigerweise deklariert und initialisiert werden. (Dabei versteht man unter Deklarieren das Festlegen von Bezeichner und Datentyp, unter Initialisieren das Festlegen des Startwertes der Variablen.) Bei der ersten Verwendung einer Variable initialisiert und deklariert PHP diese Variable automatisch mit einer NULL-Referenz, das bedeutet eigentlich nichts anderes, als dass die Variable keinen Inhalt besitzt.

### Explizite Initialisierung

Eine explizite Deklaration und Initialisierung lässt sich natürlich ebenfalls machen und wird im Allgemeinen auch als saubere Programmierung betrachtet. Dabei wird allen Variablen vor ihrem ersten möglichen(!) Auftreten entweder ein neutraler oder ein Standard-Wert zugewiesen. Dies kann zum Beispiel am Anfang der Datei oder vor einer Schleife sein, in der die Variable verwendet werden soll. Die Zuweisung erfolgt generell über den Zuweisungsoperator =.
Die Variable $variable wird mit dem Wert 0 initialisiert. Die Variable $text wird mit einem leeren String initialisiert. Dieser Operator lässt sich auch bei späteren Manipulationen des Inhaltes verwenden, ist also nicht auf die Initialisierung einer Variable beschränkt. (siehe "Zuweisung")

#### Bedingte Zuweisung

Eine bedingte Zuweisung (auch: ternärer Operator) kombiniert eine Abfrage mit einer Zuweisung:
Wenn $frage wahr oder ein Äquivalent dazu ist, so wird der Variable $wert der Wert von $wahr zugewiesen, ansonsten der Wert von $falsch. Dabei können alle Variablen auch direkte Werte, Konstanten oder Ausdrücke sein. Diese Schreibweise ist für einfache Abfragen kompakter, als das Äquivalent über if-Abfragen:
Das folgende Beispiel weist der Variable nur einen Standard-Wert zu, wenn sie nicht existiert, also nicht deklariert wurde.

## Zuweisung

Die Zuweisung erfolgt durch den Zuweisungsoperator in Gestalt des Ist-Gleich-Zeichens (=):
Nach der Zuweisung erhält die Variable text den String "Hello world" und die Variable eine_zahl den Wert 42.
Statt einem festen Ausdruck kann man auch z.B. den Inhalt einer anderen Variable in eine Variable speichern:
Damit erhält auch die Variable text2 die Zeichenkette "Hello World".
Dieses Zuweisung kann man auch anders lösen:
Nun enthalten die Variablen text1 und text2 die Zeichenkette "Hello World". Dies ist von Vorteil, wenn man zwei Zuweisungen mit der gleichen Zeichenkette benötigt. Man spart somit eine Zuweisung.
Wenn man an einen String eine weitere Zeichenkette anhängen will, so kann dies mit einem .= erreicht werden:
Die Variable $text würde jetzt Hello World! beinhalten. Der Zuweisungsoperator .= ist eine Kombination aus dem Zuweisungsoperator = und dem Vereinigungsoperator ., welcher zwei Ausdrücke miteinander verbindet. Alternativ hätte man auch Folgendes schreiben können:
Jetzt haben Sie gelernt, wie man Variablen zuweist. Das folgende Programm gibt die Variable aus:
Es wird Hello World! ausgegeben. Beachten Sie bitte, dass die Ausgabe von Variablen ohne Hochkommata oder Anführungsstriche erfolgt.
Wenn man bei einer Ausgabe Text und Variablen kombinieren will, sieht dies mit Hochkommata wie folgt aus:
Innerhalb von Anführungszeichen aber werden Variablen geparst (Englisch: parsed), also vom Interpreter gegen die ihnen zugewiesenen Werte ausgetauscht:
In beiden Fällen wird Der Computer sagt Hello World! ausgegeben.
Aus bestimmten Gründen, von denen der einfachste die Verwendung von XHTML-Attributen mit zwingend vorgeschriebenen Anführungszeichen ist, wird es immer wieder vorkommen, dass man das Parsen blockierende Hochkommata und das Parsen erlaubende Anführungszeichen zu kombinieren hat. Auch in unserem Beispiel könnte man diese Kombination anwenden, um die direkte Rede korrekt darzustellen:
Mit diesem Code wird "Der Computer sprach die Worte 'Hello World!' zu uns." ausgegeben.
Um beim Schreiben nicht zu sehr verwirrt zu werden, was Programmablauf und was Werte sind, bietet sich ein Editor mit Syntaxhervorhebung (Englisch: Syntax highlighting) an. Damit sind beide Elemente leicht voneinander zu unterscheiden.

### Referenzierung

Variablen sind nicht gleichzusetzen mit dem Inhalt, den sie besitzen. Eine Variable mit dem Inhalt "Hallo Welt" ist also nicht identisch mit der Zeichenkette, sondern verweist bloß auf die Speicherstelle, die den Inhalt speichert. Für den praktischen Einsatz macht dies keinen Unterschied, da PHP durch den Aufruf der Variable gleich auf den Inhalt verweist. Man kann allerdings auch direkt auf die Referenz verweisen, indem man den Referenz-Operator "&" nutzt. So verweist &$foo nicht auf den Inhalt der Variable $foo, sondern auf deren Speicherstelle.
Dies wird allerdings erst wirklich interessant für Funktionen und Objekte. Ansonsten ergibt es wenig Sinn, für eine Speicherstelle zwei Variablen zu nutzen.

## Konstanten

Es gibt immer wieder Situation, in denen man es mit einer „Variablen“ zu tun hat, welche sich nicht ändern soll. Solche Variablen haben also immer den gleichen Wert, der Wert bleibt konstant. Man nennt sie daher nicht Variablen, sondern Konstanten. Der Zugriff und das Speichern von Konstanten ist anders als bei Variablen. Man benutzt zum Definieren die Funktion define, zum Lesen einer Konstanten gibt man einfach nur den Namen der Konstante an ohne das Dollarzeichen!
Konstanten werden, damit man sie besser erkennen kann, immer groß geschrieben, und mehrere Wörter durch einen Unterstrich getrennt. Für die Konstanten existiert kein Zugriffsbereich wie für Variablen, sie können von überall gelesen werden.
Mehr über Konstanten im entsprechenden Kapitel.

## Dynamische Variablen

Manchmal kommt es vor, dass man eine Variable benötigt, deren Name sich ändert, je nachdem was für ein Code davor ausgeführt wurde. Damit man nicht für jede Variable überprüfen muss, ob diese nun gesetzt ist, gibt es dynamische Variablen. Die dynamische Variable unterscheidet sich nur insofern von normalen Variablen, als beim Angeben des Variablennamens eine weitere Variable benutzt wird. Allerdings erhöhen dynamische Variablen die Zeit für nachträgliche Änderungen meist stark und sollten daher nur in besonderen Fällen verwendet werden.
Zuerst wird eine Variable definiert welche den Namen der benötigten Variable beinhaltet und dann die Variable mit dem Namen. Am Schluss wird dann zuerst das "innere" $varname zum String "text" umgewandelt und dann der Inhalt der neuen Variable $test ausgegeben.
Wie schon bei den Variablen in Strings gibt es auch hier das Problem, dass eine dynamische Variable vielleicht nur teilweise dynamisch ist. Das folgende Beispiel verdeutlicht das Problem:
Der Name der Variable kann genauso wie bei den Strings auch hier in geschweifte Klammern gesetzt werden, um genau zu kennzeichnen, wo die Variable anfängt und wo sie aufhört.
Dynamische Variablen kommen sehr selten zum Einsatz, da sie nur in besonderen Situationen erforderlich sind.

## Übungen

So, nun wieder eine kleine Aufgabe, damit du prüfen kannst, ob du aufmerksam gelesen hast:
* In einem Script soll eine Konstante mit der Zahl 5 existieren und eine Variable mit 4. Diese beiden sollen addiert und dann ausgegeben werden. Wird der Wert der Variable oder Konstante verändert, soll sich das Ergebnis automatisch anpassen.

# Konstanten

Websiteentwicklung PHP Konstanten
In PHP bezeichnet man Konstanten als solche Ausdrücke, die im Gegensatz zu Variablen ihren Wert nicht ändern können. Konstanten definiert man beispielsweise für globale Einstellungen oder um Parameterwerte einen besseren merkbaren Ausdruck zu geben. Für die allgemeine Übersichtlichkeit schreibt man Konstanten immer groß!
Konstanten werden in PHP mit der Funktion define definiert. Der erste Parameter ist der Name der neuen Konstante und der zweite Parameter ist der Wert dieser Konstante.
Diese Konstanten sind gegenüber Variablen überall im Script vorhanden. Somit kann man ohne Problem auch innerhalb von Funktionen und anderen Blöcken auf Konstanten zugreifen.
Ein Beispiel für die Benutzung der Konstanten ist die error_reporting-Funktion. Laut der Funktionsbeschreibung muss man dieser Funktion eine Zahl übergeben um das Error-Log-Level einzustellen. Da es aber mehr als 10 Werte von error_reporting gibt, die auch noch beliebig kombiniert werden können, ist es fast unmöglich sich die Zahlen der Kombinationen zu merken. Hier kommen nun die Konstanten in Spiel. In PHP gibt es nun Konstanten der Form E_*, beispielsweise E_ERROR oder E_USER_NOTICE. Es ist möglich die Funktion wie folgt aufzurufen.
Mit den Konstanten kann man diese Funktion auch wie folgt aufrufen:
Anhand der Konstanten kann man erkennen, was die Funktion eigentlich machen soll. In diesem Fall das Error-Log-Level so einstellen, das nur Error, Parse-Error und Benutzer-Warnungen angezeigt werden. So kann jeder Programmierer erkennen, was die Funktion macht bzw. mit welchen Parameter diese Funktion aufgerufen wird.
Wenn man überprüfen möchte, ob eine Konstante vorhanden ist, nutzt man defined.
Die Funktion wird häufig verwendet um Entwickler-Code zu verstecken (wenn sich ein Programmierer einloggt, wird die Konstante gesetzt, ansonsten nicht um dann ggf. Debug-Information auszugeben).

# Arrays

Websiteentwicklung PHP Arrays

## Numerische Arrays

Ein Array ist ein Feld, welches verschiedene Elemente, verschiedenen Typs enthalten kann. Diese werden dann über ihren Index angesprochen. Das erste Element bekommt den Index 0, das zweite Element bekommt den Index 1 usw. .
Um Arrays zu erstellen, verwendet man das Sprachkonstrukt array. Auch wenn die Benutzung vergleichbar mit der einer Funktion ist, handelt es sich um keine Funktion!
Im folgenden wird ein eindimensionales Array namen erstellt:
Die einzelnen Einträge werden dann über ihren Index aufgerufen:
Ausgabe:
Beachten Sie, dass die Nummerierung bei 0 anfängt! In unserem Beispiel wird also der dritte Name Tina ausgegeben, und nicht wie vielleicht erwartet Anton. Das Nichtbeachten dieser Eigenschaft kann leicht zu Fehlern führen.

## Assoziative Einträge

Es ist aber auch möglich, für die einzelnen Einträge Namen zu vergeben, mit denen die Einträge angesprochen werden:
Um den Namen Max ausgeben zu lassen, müsste man das schreiben:
Ausgabe:

## Hinzufügen von Einträgen

Um neue Elemente in ein Array hinzuzufügen kann man folgende Syntax verwenden:

## Mehrdimensionale Arrays

Arrays können beliebig viele Dimensionen haben. Das heißt, sie können beliebig verschachtelt sein.
Ein 2-dimensionales Array kann folgendermaßen erstellt werden:
Das numerische Array $personenliste enthält nun zwei Felder, die wiederum jeweils vier Felder enthalten.
Auf beispielsweise die zweite Adresse kann nun wie folgt zugegriffen werden:
Ausgabe:
* Hinweis
* In PHP kann auch nach dem letzten Array-Eintrag ein Komma stehen. Dies ist hilfreich, wenn die Arrays später manuell (im Editor) erweitert, verkürzt oder umsortiert werden. Auf diese Weise kann man Parsing-Fehler vermeiden, da insbesondere große Arrays (z.B. zur Konfiguration einer Anwendung) schnell recht unübersichtlich werden.

## Zählen der Einträge

Das Zählen der Einträge erfolgt durch die Funktion Count:

## Einträge durchsuchen

Wenn man ein Array nach einem Eintrag durchsuchen will, geht das so:
Wenn man den Index eines Wertes dabei zurückgeliefert haben will, geht das so:

## Sortieren der Einträge

Man kann Arrays auch sortieren. Möchte man die Werte sortieren, geht das mit asort:
Wenn man aber nach den Namen der Werte sortieren lassen will (falls welche zugeteilt wurden) benutzt man ksort.
Um die Werte bzw. Namen der Einträge in umgekehrter Reihenfolge zu sortieren, verwendet man krsort bzw. arsort.
Manche Arrays, etwa mehrdimensionale, oder solche, die Instanzen von Klassen (Objekte) Inhalten, können nicht so einfach sortiert werden, dass die genannten Funktionen benutzt werden können. Für kompliziertere Sortieralgorithmen kann man sich eine eigene Funktion schreiben. Um die $personenliste aus dem Abschnitt "Mehrdimensionale Arrays" nach Postleitzahlen zu sortieren, kann wie folgt vorgegangen werden:
Der Funktion usort wird neben dem zu sortierenden Array auch der Name der eigenen Sortierfunktion übergeben. Die Sortierfunktion muss:
* Wenn das erste Feld (hier $a) vorgestellt werden soll, -1 zurückgeben.
* Wenn die beiden Felder nicht getauscht werden sollen, 0 zurückgeben.
* Wenn das zweite Feld (hier $b) vorgestellt werden soll, 1 zurückgeben.
Um in einer Sortierfunktion Strings zu sortieren, kann strcmp($string1, $string2) verwendet werden, strcmp gibt wie erwartet -1, 0 oder 1 zurück.
Da man mit der Sortierung von Arrays allein nichts anfangen kann, kommt jetzt die Schleife Foreach.

## ein Array durchlaufen – foreach

Mit dem foreach-Konstrukt kann über ein Array oder ein Objekt iteriert werden, das heißt alle Einträge werden nacheinander in einer Schleife aufgerufen und können dann verwendet werden. Die foreach-Schleife ist die einfachste Möglichkeit ein Array oder Objekt zu durchlaufen. Alle Einträge eines Arrays werden in jedem Schleifendurchlauf einer Variable zugewiesen, deren Name nach dem Schlüsselwort as angegeben wird.
Benötigt man zusätzlich den Schlüssel (Bezeichner in einem assoziativem Array) zu jedem Wert, kann dieser durch folgende Syntax in jedem Schleifendurchlauf gefüllt werden:

## End

Mit end springt man an das Ende eines Arrays und gibt diesen Wert zurück
Ausgabe: Claudia

## Arrays analysieren

Sollte es einmal notwendig sein, ein Array, das eventuell selbst aus Arrays besteht, genauer zu untersuchen, kann die Funktion var_dump verwendet werden:
Dies generiert folgende Ausgabe.
Alternativ kann man die weniger komplexe Funktion print_r verwenden. Um eine Ausgabe zu erhalten, welche geparst werden kann (also die eigentliche Array-Notation), kann var_export verwendet werden.

## Arrays und Objekte

Sehr hilfreich ist zuweilen auch die Eigenschaft, dass sich Objekte in Arrays und Arrays in Objekte casten lassen. Außerdem können beide Typen gleichermaßen mit einer foreach-Schleife durchlaufen werden. Als nettes Schmankerl gibt es auch noch das ArrayObject, welche Klassenmethoden aufweist, aber auf die Inhalte wird wie bei einem Array zugegriffen.
Beispiele für casting:
Ausgabe:
Ausgabe:

# Operatoren

Websiteentwicklung PHP Operatoren

## Übersicht

Die folgende Tabelle zeigt die Rangfolge der Operatoren und die Richtung in der sie ausgewertet werden. Oben steht der Operator mit dem höchsten Rang.
| von | Operator |
| keine Richtung | new |
| rechts | [ |
| rechts | ! ~ ++ -- (int) (float) (string) (array) (object) @ |
| links | * / % |
| links | + - . |
| links | << >> |
| keine Richtung | < <= > >= |
| keine Richtung | == != === !== |
| links | & |
| links | ^ |
| links | | |
| links | && |
| links | || |
| links | ? : |
| rechts | = ^= <<= >>= |
| rechts | print |
| links | and |
| links | xor |
| links | or |
| links | , |

## Arithmetische Operatoren

Arithmetische Operatoren sind Rechenoperatoren. Rechenzeichen sind Pluszeichen (+) für die Addition, Minuszeichen (-) für die Subtraktion, ein Stern (*) für die Multiplikation, ein Schrägstrich (/) für die Division und ein Prozentzeichen (%) für die Modulo-Operation (Rest einer Division).

### Beispiele: Variablen

Zuerst das Rechnen mit zwei Variablen:

### Beispiele: Variablen und Zahlen

Jetzt das Rechnen mit einer Variable und einer Zahl

### Beispiele: Zahlen

Und schließlich das Rechnen nur mit Zahlen:

## Zuweisungsoperatoren

Der einfachste Zuweisungsoperator ist "=". Er weist der Variablen auf seiner linken Seite den Ausdruck auf seiner rechten Seite zu.
Zu beachten ist, dass auf der linken Seite eine Variable stehen muss. Eine Zuweisung wie
ist absolut gültig, sie wird von rechts nach links ausgewertet. $a erhält also den Wert 5 und dann erst $b. Eine Zuweisung wie
ist dagegen ungültig. Eine korrekte Schreibweise wäre hingegen:
Nach dieser Anweisung enthält $a den Wert 5 und $b den Wert 6.
Neben dem einfachen Zuweisungsoperator gibt es einige "kombinierte Operatoren":

## Inkrement- und Dekrementoperatoren

| Beispiel | Name | Auswirkung |
| ++$a | Prä-Inkrement | Erhöht den Wert von $a um eins (inkrementiert $a) und gibt anschließend den neuen Wert von $a zurück. |
| $a++ | Post-Inkrement | Gibt zuerst den aktuellen Wert von $a zurück und erhöht dann den Wert von $a um eins. |
| --$a | Prä-Dekrement | Vermindert den Wert von $a um eins (dekrementiert $a) und gibt anschließend den neuen Wert von $a zurück. |
| $a-- | Post-Dekrement | Gibt zuerst den aktuellen Wert von $a zurück und erniedrigt dann den Wert von $a um eins. |

### Beispiel
## Bit-Operatoren

Bit-Operatoren verändern die einzelnen Bits einer Variablen. Sie lassen sich wie arithmetische Operatoren auf jeden Ausdruck anwenden. Man kann also auch 34 >> 3 schreiben, anstatt die Werte vorher einer Variable zuzuweisen. Jede Ganzzahl stellt sich für den Rechner als Binärzahl dar. So wird beispielsweise 66 durch 1000010 repräsentiert.
Der Bit-Operator & (und) setzt alle Bits, die in $a und $b gesetzt sind.
Der Bit-Operator | (oder) setzt alle Bits, die in $a oder $b gesetzt sind.
Der Bit-Operator ^ (exklusiv oder) setzt alle Bits, die in $a oder $b, aber nicht in beiden gesetzt sind.
Der Bit-Operator ~ (nicht) setzt alle Bits, die nicht gesetzt sind, und löscht alle Bits, die gesetzt sind.
Der Bit-Operator << (nach links verschieben) verschiebt alle Bits seines linken Operanden um die im rechten angegebene Zahl nach links.
Der Bit-Operator >> (nach rechts verschieben) verschiebt alle Bits seines linken Operanden um die im rechten angegebene Zahl nach rechts.

### Bit-Operatoren als Flags

Eine praktische Anwendung von Bit-Operatoren ist die Verwendung als Flags, etwa in einem Rechtesystem:

#### Ausgabe

Zu Beachten ist, dass Flags der gleichen Gruppe (hier: die einzelnen Rechte), bedingt durch das Binärsystem, voneinander verschiedene Potenzen der Zahl 2 sein müssen.

## Vergleichs-Operatoren

Die Vergleichs-Operatoren geben eine Booleanschen Ausdruck (true oder false) zurück. Sie lassen sich auf jeden Ausdruck anwenden.
| Operator | Bedeutung | Ergebnis |
| $a == $b | Gleich | Gibt true zurück, wenn $a gleich $b ist. echo (325.0 == 325); // wahr - Anzeige ist "1" |
| $a === $b | Identisch | Gibt true zurück, wenn $a gleich $b ist und beide vom gleichen Typ sind (nur ab PHP 4). echo (325.0 === 325); // falsch - Anzeige ist leer |
| $a != $b | Ungleich | Gibt true zurück, wenn $a nicht gleich $b ist. |
| $a <> $b | Ungleich | Gibt true zurück, wenn $a nicht gleich $b ist. |
| $a !== $b | Nicht identisch | Gibt true zurück, wenn $a nicht gleich $b ist, oder wenn beide nicht vom gleichen Typ sind (nur ab PHP 4). |
| $a < $b | Kleiner Als | Gibt true zurück, wenn $a kleiner als $b ist. |
| $a > $b | Größer Als | Gibt true zurück, wenn $a größer als $b ist. |
| $a <= $b | Kleiner Gleich | Gibt true zurück, wenn $a kleiner oder gleich $b ist. |
| $a >= $b | Größer Gleich | Gibt true zurück, wenn $a größer oder gleich $b ist. |

## Logische Operatoren

| Beispiel | Name | Auswirkung |
| $a and $b | Log. UND | TRUE wenn sowohl $a als auch $b TRUE ist. |
| $a or $b | Log. ODER | TRUE wenn $a oder $b TRUE ist. |
| $a xor $b | Exklusives Log. ODER | TRUE wenn entweder $a oder $b TRUE ist, aber nicht beide. |
| ! $a | Log. NICHT | TRUE wenn $a nicht TRUE ist. |
| $a && $b | Speziell | TRUE wenn sowohl $a als auch $b TRUE ist. $b wird nur überprüft falls $a true war. |
| $a || $b | Speziell | TRUE wenn $a oder $b TRUE ist. $b wird nur überprüft falls $a false war. |

## Array-Operatoren

Das Pluszeichen (+) reduziert zwei oder mehrere Arrays auf ein einziges. Dabei erhält das neue Array alle Werte mit entsprechender Zugehörigkeit zum jeweiligen Schlüssel/Index. Falls die ursprünglichen Arrays unterschiedliche Werte zu einem Schlüssel aufweisen, so erhält dieser Schlüssel des neuen Arrays den Wert des zuerst angegebenen Arrays.

### Beispiele

Die Arrays werden zu einem Array zusammengefasst
Der unterschiedlich belegte Schlüssel "Schluessel" erhält den Wert des zuerst angegebenen Arrays $array1

## Der Zeichenketten-Operator .

Der Zeichenketten-Operator ist der Punkt (.), er liefert als Ergebnis eine Zeichenkette die sich aus seinem linken und seinem rechten Argument zusammensetzt.

### Ausgabe
## Der Auswahl-Operator ?:

Dieser besondere Operator ist gewissermaßen eine verkürzte Version von if-else. Er wird ternärer Operator genannt.

### Syntax

boolwert kann jeder Booleansche Ausdruck sein, ergibt die Auswertung true wird bei_true zurückgegeben, andernfalls bei_false.

### Ausgabe
## Der Fehler-Kontroll-Operator @

Wird einem Funktionsaufruf oder einer Variable der @-Operator vorangestellt, unterdrückt dies die von PHP generierten Fehlermeldungen. In Kombination mit dem or-Operator und der Funktion die lassen sich so eigene Fehlermeldungen generieren.

### Anwendungsbeispiel

Die Funktion mysql_connect stellt eine Verbindung zu einem Datenbankserver her. Falls die Verbindung fehlschlägt, liefert die Funktion false zurück und gibt eine PHP-Fehlermeldung aus (durch @ unterdrückt). Der Operator wertet seinen rechten Ausdruck nur aus, wenn der linke false ergab (die wird also nur dann ausgeführt). Die Funktion die bricht schließlich das Script ab und gibt den an sie übergebenen Text aus.

# Kontrollstrukturen

Websiteentwicklung PHP Kontrollstrukturen

## Einfache Abfragen

Mit if kann man mit Hilfe der Vergleichsoperatoren Werte abfragen und je nachdem etwas bestimmtes ausführen lassen. Das Grundgerüst einer if-Abfrage sieht so aus:
Zuerst kommt ein if mit der Bedingung in Klammern. Gibt diese Bedingung true (wahr) zurück, ist also erfüllt, wird das, was zwischen den beiden geschweiften Klammern steht, ausgeführt. Liefert sie false zurück, ist also nicht erfüllt, überspringt der Interpreter den Teil, der in den geschweiften Klammern steht und arbeitet danach normal weiter. Zu beachten ist, dass in der Zeile mit der Bedingung kein Strichpunkt am Ende steht, ebenso wie bei der geschweiften Klammer zu. Ein Beispiel für eine if-Abfrage:
Dieses Script gibt Du bist Hans aus, wenn die Variable Benutzername gleich Hans ist. Ist dies nicht der Fall, passiert gar nichts.
Bitte beachten Sie: Der Vergleich benutzt in PHP stets zwei Gleichheitszeichen (==). Falsch wäre:
In diesem Beispiel würde der Interpreter zunächst der Variablen $benutzername den Wert 'Hans' zuweisen und dann den String prüfen. In diesem speziellen Fall wäre also die Abfrage immer TRUE. Man kann diese Variante allerdings dazu nutzen, eine Zuweisung mit einer Abfrage zu koppeln.
Für den Fall, dass nur eine Anweisung nach der Abfrage folgt, darf man die geschweiften Klammern weg lassen.

## Typsichere Abfragen

Manchmal ist es notwendig, auch den Datentyp in der Überprüfung zu berücksichtigen. Dafür werden in der Abfrage drei, statt zwei Gleichheitszeichen verwendet.
Beispiel:

## Else und Elseif

Eine einfache If-Abfrage macht immer, wenn die Bedingung nicht zutrifft, gar nichts. Mit else kann man bestimmen, was passieren soll, wenn die Bedingung nicht zutrifft. Das Grundgerüst einer If-Abfrage mit else sieht so aus:
Als Erweiterung für else gibt es elseif. Elseif führt immer dann, wenn die erste Bedingung nicht zutrifft und eine andere Bedingung zutrifft, etwas aus. Das Grundgerüst von Elseif sieht so aus:
Zum Beispiel wollen Sie jetzt eine Abfrage von der Variable Benutzername durchführen. Wenn der Benutzername gleich Hans ist, soll du bist Hans ausgegeben werden, ist er gleich Anton , du bist Anton und ist er anders dich kenne ich nicht:

###### Alternative Schreibweise

Es gibt in PHP eine alternative Schreibweise, die keinerlei besondere Funktion besitzt, aber bei komplexeren Strukturen die Übersicht steigern kann. Bei der Schreibweise wird die Anweisung nach der Abfrage durch einen Doppelpunkt (:) eingeleitet und durch ein "endif" beendet.
Mit elseif und else wird ebenso umgegangen
Der Vorteil liegt bei komplexen Strukturen, wo es teilweise schwer fällt herauszufinden, wozu die geschweifte Klammer am Ende einer Anweisung gehören kann.

###### Trinäre Zuweisung

Eine Besonderheit bildet eine Kurzschreibweise für Abfragen, die ohne elseif auskommen und für if und else jeweils nur eine Rückgabe besitzen.
In diesem Fall wird geprüft, ob $bar TRUE ist. Sollte $bar TRUE sein, so wird $wennwahr $foo zugewiesen, ansonsten wird $wennfalsch $foo zugewiesen. Interessant ist das für verkürzte Schreibweisen von ansonsten übermäßig komplex anmutenden Abfragen. Eine interessante Anwendung wäre zB, falls eine Variable einen Standard-Wert bekommen soll, falls (und nur dann) die Variable keinen Wert besitzt.

# Switch-Abfrage

Websiteentwicklung PHP Switch Abfrage

## Die switch-Funktion

Die switch-Anweisung ist im Prinzip eine Erweiterung der if-Anweisung. Der Vorteil hier ist, dass man die Variable gleichzeitig auf mehrere Zustände hin untersuchen kann und diesen Zuständen unterschiedliche Befehle oder auch ganze Funktionen zuordnen kann.
Am besten erklärt sich das an einem Beispiel:
Hier wird die Variable $var untersucht. Der Code hinter case "1": wird ausgewertet, wenn die Variable gleich 1 ist. Die Auswertung des Codes endet an der Stelle break;. Die Anweisung break; sollte also immer angegeben werden, sonst werden die anderen Ausgaben "Die Variable ist 'k'" und "Die Variable ist weder '1' noch 'k'" auch ausgegeben. Die Bedingung der switch-Anweisung wird nämlich nur ein mal geprüft. Ist die Bedingung wahr, werden alle folgenden Befehle und Anweisungen ausgeführt. Um dies zu vermeiden, beendet man die switch-Anweisung mit break;.

### Durchfall

HINWEIS: Manchmal ist es auch erwünscht, das break; wegzulassen, so etwas nennt sich Durchfall. Wenn man einen Durchfall benutzen will, so sollte man mit einem Kommentar darauf hinweisen.
Beispiel:
Trifft keiner der ersten beiden Fälle zu, wird der Code hinter default: ausgeführt. Dieser Eintrag sollte immer an letzter Stelle in der switch-Anweisung stehen. Die Angabe von break; ist hier nicht mehr notwendig, da die switch-Anweisung hier sowieso zu Ende ist.

### Alternative Syntax

Ebenfalls ist wieder eine Alternative Syntax möglich.

# Schleifen

Websiteentwicklung PHP Schleifen
Neben einfachen Abfragen kann man in PHP auch mit Schleifen arbeiten, d.h. etwas wird so lange ausgeführt, bis eine Bedingung erfüllt oder nicht mehr erfüllt (je nach Schleifenart) ist.

# While-Schleifen

Ein while-Schleife wiederholt den in geschweiften Klammern enthaltenen Codeblock solange, wie die angegebene Bedingung wahr (also true) ist.
Eine while-Schleife sieht zum Beispiel so aus:
Die Schleife überprüft, ob $zahl != 100 ist. Wenn ja, wiederholt sie die Anweisungen in den geschweiften Klammern, die bewirken, dass der Inhalt von $zahl ausgegeben wird und $zahl um eins erhöht wird.
Wenn $zahl den Wert 100 enthält, ist die Bedingung "$zahl != 100" falsch und die Schleife wird abgebrochen.

# Do-While-Schleifen

Syntax einer Do-While-Schleife:
Hier ein Beispiel für eine Do-While-Schleife:
Diese Schleife gibt die Zahlen von 0 bis 100 aus. Im Gegensatz zur While-Schleife wird hier zuerst die Variable ausgegeben und hinterher überprüft, ob 100 erreicht wurde. Das heißt: Auch, wenn man die Variable am Anfang gleich auf hundert setzen würde, würde trotzdem "100" ausgegeben werden. Die Do-While-Schleife sollte man also benutzen, wenn die Befehle mindestens einmal ausgeführt werden sollen. Oft kann man aber beide While-Schleifen verwenden.

# For-Schleifen

Neben While-Schleifen gibt es auch For-Schleifen. Diese sind ähnlich aufgebaut.
Als erstes wird bei "Initialisierung" eine Variable mit einem Wert belegt. Bei "Bedingung" wird geprüft, ob die Bedingung wahr ist, wenn ja wird die Schleife wiederholt, wenn nicht beendet. "Aktualisierung" wird nach jedem Durchlauf aufgerufen.
Dazu ein Beispiel
Auch diese Schleife gibt die Zahlen 0 bis 99 zurück.

# Foreach-Schleifen

Um ein Array zu durchlaufen, gibt es die Foreach-Schleife.
Eine foreach-Schleife sieht folgendermaßen aus: foreach($array as $aktuelles_element) oder bei Assoziativen Arrays foreach($array as $eintrags_name => $aktuelles_element)
Beispiel
Ausgabe:

# Verwendung der verschiedenen Typen

(Do-)While-Schleifen werden meistens verwendet, wenn zu Beginn der Schleife nicht klar ist, wie oft diese durchlaufen werden soll. Dies ist z.B. bei MySQL-Abfragen der Fall. Meist wird in der Bedingung überprüft, welchen booleschen Wert (d.h. true oder false) eine Variable oder Funktion zurückliefert. For-Schleifen werden dagegen nur verwendet, wenn die Anzahl der Durchläufe klar ist. Foreach-Schleifen werden ausschließlich zum durchlaufen eines Arrays verwendet. In Versionen vor PHP 4, in denen es die Funktion noch nicht gab, wurde eine While-Schleife mit einer speziellen Bedingung benutzt:
Beides ergibt das selbe Ergebnis:
Da es heute nur noch wenige Webserver gibt, die eine Version von PHP 3 installiert haben, wird normalerweise der einfachere Weg mittels foreach gewählt.

# Funktionen

Websiteentwicklung PHP Funktionen

## Standardfunktionen

Funktionen sind Anweisungen in PHP, die je nach Definition bestimmte Aufgaben erfüllen. Funktionsaufrufe in PHP haben immer den selben Aufbau. Zu einem bestehen sie aus den Namen der Funktion sowie diversen Parametern, wenn die Funktion welche hat und benötigt. Der Aufbau ist wie folgt definiert:
Am Anfang steht der Name der Funktion, die man aufrufen möchte. In der Funktionsreferenz von PHP (oder in der Funktionsliste) finden sie eine Liste von Funktionen, die sie in PHP benutzen können. Beachten sie, dass manche Funktionen deaktiviert bzw. nicht installiert sind. Nach dem Namen der Funktion kommt eine öffnende Klammer ("("). Nun können Parameter für diese Funktion folgen. Mehrere Parameter müssen durch Kommata getrennt werden. Nach den Parametern (falls welche vorhanden sind) kommt eine schließende Klammer(")"). Wie (fast) alles andere in PHP muss jeder Ausdruck in PHP mit einem Semikolon abgeschlossen werden, so auch ein Funktionsaufruf.
Jeder Teil eines Funktionsaufrufs (Funktionsname, Klammer, Parameter, Kommata, Semikolon) kann mit Leerzeichen oder anderen Whitespaces (Leerzeichen, Zeilenumbrüche, Tabulatoren ...) getrennt werden. Folgende Funktionsaufrufe sind äquivalent und funktionieren gleich:
Da jedoch manche Funktionsaufrufe unleserlich aussehen, werden nur bestimmte Formatvarianten verwendet. Üblicherweise benutzt man den PEAR Coding Standard für seine Skripte. In diesem Fall benutzt man die zweite Variante für Funktionsaufrufe, also nach jedem Komma in der Parameterliste ein Leerzeichen.

## Eigene Funktionen

Es gibt in PHP auch die Möglichkeit, eine eigene Funktionen zu erstellen. Diese muss man zunächst definieren. Das geschieht mit Hilfe des Schlüsselwortes function:
Danach kann man diese Funktion wie jede Standardfunktion von PHP nutzen.
Beispiel:
Das Ergebnis:
Vorteil: Man braucht einen Codeschnipsel nur einmal erstellen, und kann ihn so oft man möchte benutzen.

### Mehrere Parameter

Ebenso ist es möglich, in einer eigenen Funktion mehrere Parameter zu benutzen. Beispiel:
Ergebnis:

### Eine unbekannte Zahl an Parametern

Eine weitere Möglichkeit besteht darin, die Variablenanzahl einer Funktion offen zu lassen und in der Funktion selbst die Variablenanzahl abzufragen. Dies ist kein sehr sauberer Programmierstil, aber dennoch möglich und wird öfters verwendet.
Beispiel:
Anwendung des Beispiels
Sicherlich ist das nicht das beste Beispiel, aber zeigt dennoch etwas, das an dieser Stelle erwähnt werden sollte.

### statische Variablen

Im obrigen Beispiel ist die Variable $a statisch, d.h. sie existiert nur in der Funktion (kann von außerhalb nicht ausgelesen werden) Sie wird dauerhaft gespeichert, und die Funktion hat jederzeit Zugriff darauf...
Eine einfache, aber durchaus sinnvolle Anwendung wäre eine Funktion, die bei jedem Aufruf eine andere Zahl zurückgibt, um Verdoppelungen zu vermeiden.

### globale Variablen

Globale Variablen existieren im gesamten Skript und können von überall aufgerufen werden. Sie müssen in Funktionen jedoch erst durch "global $variablenname" bekannt gemacht werden.
Hinweis: wenn man nur innerhalb der Funktion eine Variable verändern will, sollte man das Array $GLOBALS verwenden ( $GLOBALS["variable_name"] )

### Closures

Closures sind anonyme Funktionen. Das heißt sie haben keinen Funktionsnamen.
Closures werden durch eine Variable angesprochen. Man benutzt sie hauptsächlich für "Callback"-Funktionen.

# Include

Websiteentwicklung PHP Include

## include, require, include_once, require_once
### include

Mittels include kann man Inhalte anderer Dateien an der Stelle einfügen, an der der Befehl steht.
Dieser Befehl fügt den Inhalt der Datei header.inc.php an der Stelle im Skript ein, an der sich der include-Befehl befindet. Und zwar genau dann, wenn der PHP-Parser diese Stelle im Script erreicht.
Den include-Befehl verwendet man zum Beispiel, um Funktionen in jedem Skript verfügbar zu machen. Anstatt in jeder Datei die Funktionen zu definieren, speichert man diese in einer eigenen Datei, die dann von jedem Skript eingebunden wird. Sinn davon ist, dass man bei Änderungen einer Funktion diese nur einmal auszubessern braucht.
Es gibt aber noch viele andere Einsatzgebiete, wo der include-Befehl Sinn macht: Und zwar beim Einbinden von Seitenelementen; z.B. ein Navigationsmenü oder ein Footer.

### require

Um sicherzustellen, dass eine Datei eingebunden wird, die z.B. wichtige Konfigurationswerte beinhaltet, welche vor Ausführung anderen Codes zur Verfügung stehen müssen, ist der Befehl require zu verwenden.
Wird die einzubindende Datei nicht gefunden, erzeugt require einen "Fatal error" und das Script wird abgebrochen. Im Unterschied dazu erzeugt include nur ein "Warning" und das Script wird weiter ausgeführt.
Innerhalb einer eingebundenen Datei können natürlich weitere include / require Befehle enthalten sein.

### include_once und require_once

Das mehrfache Definieren einer Funktion ist verboten. Um sicherzustellen, dass eine solche Datei nicht mehrfach eingebunden wird, gibt es die Befehle include_once und require_once. Der Parser sorgt dann dafür, dass dies nicht geschieht. Ansonsten verhalten sich diese beiden Varianten wie Ihre Äquivalente require und include.
Achtung: Wenn require_once auf einem System eingesetzt wird, das nicht zwischen Groß- und Kleinschreibung auf dem Dateisystem unterscheidet (bspw. Windows Server auf FAT), kann ein und dieselbe Datei unter Umständen mehrfach eingebunden werden, wenn sich die Schreibweise im PHP-Skript zwischen den Aufrufen unterscheidet.
Zusätzliche Informationen im PHP-Manual
* include
* include_once
* require
* require_once

# MySQL

Websiteentwicklung PHP MySQL

## Kurze Einführung in MySQL

MySQL ist eines der populärsten Datenbanksysteme der Welt, nicht zuletzt, da es ein Open Source Projekt ist. Egal ob privat oder geschäftlich - heute ist MySQL bereits über elf Millionen (Quelle: http://www.mysql.com/company/factsheet.html) mal installiert. Das System ist einfach aufgebaut, sehr schnell und die Grundzüge sind vergleichbar einfach zu verstehen. MySQL wird von Counter, über Gästebücher und Suchfunktionen, bis hin zu komplexen Content Management Systemen oder Online-Shops verwendet.
Eine einzelne Datenbank kann man sich als Sammlung von Tabellen vorstellen. Jede Tabelle hat wie gewohnt Zeilen und Spalten. Die Spalten können benannt werden, aber die Datensätze in der Tabelle (also die Zeilen) sind nicht geordnet. In einer Zelle können Zahlen, Text-Strings und auch Boolean Werte gespeichert werden (binäre Dateien, wie beispielsweise Bilder können ebenfalls gespeichert werden - davon wird aber abgeraten). An dieser Stelle wird gezeigt wie es mit PHP möglich ist Tabellen zu erstellen und diese dann mit Daten zu füllen.
Die Kommunikation mit einer MySQL-Datenbank erfolgt über die Abfragesprache SQL – siehe auch Einführung in SQL.

## Verwendung von MySQL
### Methodenübersicht

PHP bietet eine Vielzahl an Funktionen, um mit dem Datenbanksystem zu kommunizieren. Hier werden nur die gebräuchlichsten erklärt:
* mysql_connect([string Server[, string Benutzername[, string Benutzerkennwort]]])Erstellt eine neue Verbindung zum MySQL-Server. Dabei müssen der Server und optional der Benutzername und das Benutzerkennwort angegeben werden.
* mysql_select_db(string database_name[, resource link_identifier]) - Nach einem Verbindungsaufbau wählt diese Funktion die Datenbank aus, in der wir mit PHP arbeiten wollen.
* mysql_query(string Anfrage[, resource Verbindungs-Kennung]) - Einer der wichtigsten Befehle: Sendet eine Anfrage an den MySQL-Server. Mit diesen Anfragen können Datensätze eingefügt, ausgelesen und gelöscht werden. Außerdem können Sie hier die Tabellen erstellen, bearbeiten und löschen.
* mysql_error([resource link_identifier]) - Diese Funktion liefert die Fehlermeldung zurück, falls eine andere MySQL-Funktion einen Fehler erzeugt hat bzw. false zurücklieferte, was auf einen Fehler hinweist. Siehe dazu http://faq.php-q.net/#mysql.
* mysql_fetch_assoc(resource Ergebnis-Kennung) - Liefert den aktuellen Datensatz, der unter der Ergebniskennung aufgerufen wurde. Ein weiterer Aufruf dieser Funktion liefert den nächsten Datensatz der Ergebnistabelle. Wenn kein Datensatz mehr vorhanden ist wird false zurückgeliefert.
* mysql_close([resource Verbindungs-Kennung]) - Schließt die Verbindung zum MySQL-Server mit der angegebenen Verbindungs-Kennung. Diese Kennung ermöglicht es, mehrere Verbindungen auf einmal zu erstellen. Wird die Verbindungs-Kennung weggelassen, wird die zuletzt geöffnete Verbindung geschlossen.
* mysql_real_escape_string(string unescaped_string[, resource link_identifier]) - Maskiert einen String zur sicheren Verwendung in einer Abfrage. Sonder- und Steuerzeichen wie " (Anführungszeichen) werden maskiert um eine Manipulation des SQL-Ausdrucks durch externe Eingaben zu verhindern.

### Beispiele

Achtung: Wenn mehr als ein Datensatz ausgewählt wird, läuft die Speicherung in einem Array anders. Denn es wird jeweils nur immer eine einzige Zeile in das Array gespeichert.
Ein Beispiel hierfür wäre: (Ausschnitt)

## Verwendung von MySQLi

MySQLi ist eine verbesserte (das i steht für improved) Erweiterung von PHP zum Zugriff auf MySQL-Datenbanken. Sie ist im Gegensatz zur ursprünglichen Variante objektorientiert, lässt sich aber auch prozedural benutzen. Ein wesentlicher Vorteil ist, dass mithilfe von sogenannten Prepared Statements SQL-Injection-Angriffe verhindert werden können.

## Verwendung von PDO

PDO (PHP Data Objects) stellt eine Abstraktionsebene für den Datenbankzugriff dar und ermöglicht einen einheitlichen Zugang von PHP auf unterschiedliche SQL-basierte Datenbanken, wie zum Beispiel MySQL, PostgreSQL oder SQLite. Dabei wird unter anderem der Portierungsaufwand beim Umstieg auf eine andere Datenbank minimiert. Es wird nur der Datenbankzugriff abstrahiert, nicht die Datenbank selbst. Für die zu nutzende Datenbank wird ein datenbankspezifischer Treiber benötigt.
-> Siehe Datenbankzugriff mit PDO

## Weblinks

* http://www.php.net/manual/de/book.mysql.php
* http://www.php.net/manual/de/book.mysqli.php

# Datenübergabe

Websiteentwicklung PHP Datenübergabe
Oft müssen Daten zwischen ein oder mehreren Seiten ausgetauscht werden. Beispiele sind Suchfunktionen (ich gebe auf einer Seite einen Text ein und erhalte die Suchergebnisse auf einer anderen Seite), Login-Formulare (ich gebe einen Benutzernamen und ein Passwort ein und werde dann eingeloggt) "Einkaufswagen" wie sie auf vielen Shopping-Webseiten zu finden sind, Kontaktformulare und vieles mehr.

## Arten der Datenübergabe

Grundsätzlich stehen vier Arten der Datenübergabe zur Verfügung:
* die Übergabe mittels URL, genannt $_GET
* die Übergabe aus einem (HTML)-Formular heraus, genannt $_POST
* die Speicherung der Daten in einer Session, $_SESSION
* die Speicherung von Daten in einem Cookie, $_COOKIE
Dieses Kapitel beschäftigt sich nur mit $_GET und $_POST!

## Welche Übergabeart wofür?

Die Art der Datenübergabe hängt hauptsächlich vom Einsatzzweck ab.
$_GET wird mit der URL übertragen und damit öffentlich, die URL kann abgespeichert und an andere verschickt werden. $_GET eignet sich damit für alles, was keine Zustandsänderung auslöst, zum Beispiel eine Suche, die Auswahl eines Artikels usw.
$_POST wird für den (normalen!) Benutzer unsichtbar im Hintergrund übertragen. Es eignet sich daher sowohl für größere Datenmengen als auch für Zustandsänderungen wie einloggen, ausloggen, den Abschluss eines Kaufes usw.
Eine Session ($_SESSION) wird auf dem Server gespeichert und ist für den Benutzer nicht erreichbar. Hier können sowohl größere Datenmengen als auch Prüfsummen gespeichert werden, um die Sicherheit zu erhöhen. Um die Daten eines Nutzers über längere Zeiträume / mehrere Seiten zu behalten, wird oft $_SESSION genutzt. Weiteres im Kapitel PHP: Sessions.
$_COOKIE wird bei dem Benutzer gespeichert. Ein Benutzer kann Cookies abstellen oder für die Webseite nicht akzeptieren.

## Variablenübergabe mit POST

Erstellen Sie als erstes zwei PHP-Dateien. Eine mit dem Namen index.php und eine andere, die index2.php heißt. In die "index.php" schreiben Sie nun
Wichtig ist dabei das Attribut method="post" im form-Tag. In die "index2.php" schreiben Sie:
method="post" sagt aus, dass PHP die Formulardaten in der globalen (Array-)Variablen $_POST ablegt. In der "index2.php" müssen die Formulardaten deshalb mit $_POST abgerufen werden.

## Sicherheitshinweise

Alle Daten, die Sie von einem Client bekommen, müssen Sie auf Gültigkeit und Sicherheit überprüfen. Wenn Sie dies vernachlässigen, kann das zu gravierenden Sicherheitsproblemen führen:
* Layout der Web-Seite wird durch falsche HTML-Tags zerstört
* Bösartige Java-Scripte manipulieren die HTML-Seite im Browser
* Illegale Inhalte können, durch dritte, auf dem Server gespeichert werden
* Ein Hacker kann eigenen PHP-Code einschleusen (die Folge: löschen/auslesen/manipulieren von Daten auf dem Server)
Vergewissern Sie sich deshalb immer, dass die folgenden Punkte erfüllt werden:
| 1.) | Variable nicht initialisiert: Dies kann dazu führen, dass eine Warnung von PHP angezeigt wird, die dem potentiellem Hacker Informationen über den Aufbau des PHP-Skriptes verrät. Verwenden Sie deshalb immer den Befehl isset; in Verbindung mit einer verkürzten If-Anweisung isset($_GET['alter']) ? $_GET['alter'] : '';</soursyntaxhighlightce> |- |valign="top" | '''2.)''' |In der übergebenen Variable ist HTML-Code oder Browser-Script-Code (JavaScript) enthalten. Wird dieser wieder im Browser ausgegeben, kann das Layout verloren gehen oder es kann "bösartiger" Java-Script-Code ausgeführt werden. Für diesen Fall müssen Sie unbedingt alle < und > "verhüllen". Am einfachsten verwenden Sie hierfür den PHP Befehl '''htmlentities''', der alle HTML Sonderzeichen umwandelt. <syntaxhighlight lang="php">htmlentities($_GET['alter'],ENT_QUOTES);</syntaxhighlight> |- |valign="top" | '''3.)''' |Sie wollen den Wert der übergebenen Variable in eine Datei speichern und es ist PHP-Code in der Variablen enthalten. Dies ist die größte Gefahr, die von einer übergebenen Variable ausgeht, da ein Hacker, wenn der diese "Speicher-Daten" von seinem Client aufrufen kann, Zugriff auf den gesamten Server erlangen kann. Um das zu verhindern sollten Sie: * Alle Dateien, die von einem PHP-Script zum Speichern von Daten genutzt werden, in einem Ordner speichern, der '''NICHT durch eine Web-Freigabe öffentlich''' ist * Aus allen Werten, die gespeichert werden sollen, die < und > entfernen. z.B. mit dem Befehl '''htmlentities;''' <syntaxhighlight lang="php">htmlentities($_GET['alter'],ENT_QUOTES);</syntaxhighlight> |- |valign="top" | '''4.)''' |Wandeln Sie alle Anführungszeichen um! Wenn Sie den erhaltenen Wert in einer Datenbankabfrage verwenden wollen, ''müssen'' Sie aufpassen, da sonst weitere SQL-Befehle wie Selects oder Inserts ausgeführt werden können. Jeder Text-Wert in eine SQL-Abfrage wird in einfache (') oder doppelte (") Anführungszeichen eingeschlossen. Enthält nun der Wert das gleiche Anführungszeichen, so wird der Wert als Befehl interpretiert. $GetValue = "ABC') UNION SELECT * FROM Tabelle_Hack WHERE ('a' = 'a"; $SQL_Query = "SELECT * FROM Tabelle_Hack WHERE (Name = '". $GetValue ."');"; echo $SQL_Query; --Ausgabe:---------------------------- SELECT * FROM Tabelle_Hack WHERE (Name = 'ABC') UNION SELECT * FROM Tabelle_Hack WHERE ('a' = 'a');"; Deshalb ist es nötig mit dem Befehl '''mysql_real_escape_string''' spezielle Zeichen zu maskieren. <syntaxhighlight lang="php">mysql_real_escape_string($_GET['alter']); //- Ersetzt spezielle Zeichen - ' wird zu \' </syntaxhighlight> Vorher sollte man jedoch prüfen, ob durch Konfigurationseinstellungen von PHP externe Daten bereits maskiert werden: <syntaxhighlight lang="PHP"> function mysql_escape(&$string) { if (get_magic_quotes_gpc) { $string = stripslashes($string); } mysql_real_escape_string($string); } array_walk($_GET, 'mysql_escape'); </syntaxhighlight> Die PHP-interne Funktion <code>array_walk</code> führt die oben definierte Funktion "mysql_escape" über alle Teile des Arrays $_GET aus. Dies kann genauso auf die Arrays $_POST oder $_COOKIE angewandt werden. <code>addslashes</code> ist möglicherweise unzureichend! |} <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Schleifen]] [[Websiteentwicklung: PHP: Schleifen|Zurück zu Schleifen]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: $_GET]] [[Websiteentwicklung: PHP: $_GET|Vor zu $_GET]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = $ GET= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: $_GET]] [[Websiteentwicklung: PHP: $_GET|$_GET]] </div> Der Array $_GET enthält den Inhalt von Variablen aus der URL. Diese Variablen werden vom User mit der Syntax '''...phpdateiname.php?variablenname=variablenwert''' in der Adresszeile des Browsers eingegeben, und von PHP in dem Array $_GET bereitgestellt. '''$PHPVariable = $_GET['Variablenname'];''' == Beispiel: Kreisberechnung mit PHP == Ein einfaches Beispiel Kreis.php könnte wie folgt aussehen: <syntaxhighlight lang="html4strict"> <!DOCTYPE html> <html> <head> <title>Kreisberechnung mit PHP</title> </syntaxhighlight> <syntaxhighlight lang="php"> <?php // Default-Wert setzen und durch Benutzereingabe überschreiben, falls diese gültig ist $radius = 0; if (isset($_GET['r'])) { // wurde überhaupt ein Wert angegeben… if (is_numeric($_GET['r'])) { // und ist er eine Zahl? if (0 < $_GET['r']) { // und ist der Radius positiv? $radius = $_GET['r']; // dann den Wert übernehmen } } } ?> </syntaxhighlight> <syntaxhighlight lang="html4strict"> </head> <body> </syntaxhighlight> <syntaxhighlight lang="php"> <?php // In einem weiteren PHP Codebereich wird dann die Verarbeitung und Ausgabe durchgeführt. if (0 != $radius) { // die ganze Berechnung soll nur ausgeführt werden, wenn wir eine Eingabe übernommen haben $umfang = 2*$radius*3.14;//Berechnung des Umfangs (2∏r), für ∏ wird 3,14 als Näherungswert genutzt $flaeche = $radius *$radius*pi;//Berechnung der Fläche (r*r*∏), für ∏ wird die (genauere) Funktion pi genutzt ?> Hier kommt das Ergebnis:<br> Der Umfang des Kreises ist: <?php echo $umfang;?><br> Die Fläche des Kreises ist: <?php echo $flaeche; } else { echo 'Kein gültiger Wert für den Radius r angegeben'; } ?> </syntaxhighlight> <syntaxhighlight lang=html4strict> </body> </html> </syntaxhighlight> === Erläuterung === Die Methode $_GET; übernimmt die Variablen aus der Kommandozeile (Adresszeile des Browsers) Beispiel: <syntaxhighlight lang="html4strict"> http://servername/ordner/dateiname.php?variablenname=variablenwert </syntaxhighlight> und schreibt sie in ein Array. Dieses kann dann ausgelesen werden um den Inhalt dieser Arrays in PHP-Variablen zu schreiben b.z.w. diesen zuzuweisen. Diese Zuweisung kann auch in der selben Zeile wie die Übernahme erfolgen z.B.: Beispiel: <syntaxhighlight lang="PHP"> $variable = $_GET['variable']; $variable2 = $_GET['variable2']; </syntaxhighlight> Im weiteren Verlauf des PHP Documentes kann dann der Inhalt der PHP Variablen verarbeitet, und in einem vom Interpreter generiertem HTML-Document mit <syntaxhighlight lang="PHP">echo "auszugebender String als HTML code";</syntaxhighlight> ausgegeben werden s.o. ==Die Übergabe von mehr als einem Parameter== Es ist möglich, mehr als eine Variable zu übergeben. Dafür muss die bestehende URL einfach um ein <code>&</code>, gefolgt von <code>variable=Wert</code>, erweitert werden. Beispiel: <syntaxhighlight lang="html4strict"> kreis.php?r=15&einheit=cm&name=Hans </syntaxhighlight> $_GET enthält nun folgende Schlüssel/Werte: * $_GET['r'] mit dem Wert '15' * $_GET['einheit'] mit dem Wert 'cm' * $_GET['name'] mit dem Wert 'Hans' == Setzen der Werte == Die Werte der Variablen können dann mit dem Zuweisungsoperator einer gültigen PHP-Variablen zugewiesen werden: Beispiel: <syntaxhighlight lang="php"> $r = $_GET['r'];// Der Radius wird der PHP-Variablen $r zugewiesen. $e = $_GET['einheit'] // Die Einheit wird der PHP-Variablen $e zugewiesen. $n = $_GET['name']// Ein Name wird der PHP-Variablen $n zugewiesen. </syntaxhighlight> ===Aufruf per Adressleiste des Browsers=== In diesem Beispiel muss die Variable <code>r</code> wie folgt in der Adresszeile des Browsers eingegeben werden: ....Kreis.php?r=123.1234 Für den Fall, dass der Wert von r eine Fließkommazahl sein sollte, ist es zwingend notwendig, diese mit dem Punkt als Dezimalzeichen einzugeben. Strings werden als solche übergeben und in das Array von <syntaxhighlight lang="php">$_GET['Hans'];</syntaxhighlight> geschrieben. ===Aufruf über einen Link=== Da die Parameter als Teil einer URL übergeben werden, ist es natürlich möglich, einen Link mit bereits gesetzten Werten auf einer anderen Seite einzubinden: <syntaxhighlight lang="html4strict"> <!DOCTYPE html> <head> <title>Aufruf über einen Link</title> </head> <body> <a href="kreis.php?r=15">Berechne Umfang und Fläche für einen Kreis mit dem Umfang 15</a> </body> </html> </syntaxhighlight> funktioniert (gegebenenfalls ist der Pfad zur Datei anzupassen). ===Aufruf über ein Formular=== Enthält ein HTML-Formular im <code>form</code>-Tag das Attribut <code>method="get"</code>, so erzeugt PHP beim Submit automatisch für alle Formularelemente in der globalen Array-Variable <code>$_GET</code> einen Eintrag. Der Wert eines Formularelementes <code><input name="eingabe"></code> ist also nach Submit über <code>$_GET["eingabe"]</code> zugreifbar. ==Nachteile von $_GET== Da es bei <syntaxhighlight lang="php">$_GET['Variablenname'];</syntaxhighlight> notwendig ist die Variablen in der Adresszeile des Browsers einzugeben, und hierbei auch noch eine definierte Syntax eingehalten werden muss (...dokumentenname.php?Variablenname=Variablenwert&Variablenname2=Variablenwert2), deren Kenntnis nicht von allen Usern vorausgesetzt werden kann, ist für das Übernehmen von Variablenwerten die Methode <syntaxhighlight lang="php">$_POST['Variablenname'];</syntaxhighlight> besser geeignet, weil der User hier nicht wissen muß wie die Daten übergeben werden. ==Escapen von Zeichen== Sollen bei der Ausgabe Zeichen erzeugt werden, die in der Sprache PHP als Steuerzeichen vorkommen, müssen diese mit einem vorangestellten escape auskommentiert werden. Beispiel: <syntaxhighlight lang="php"> echo "Dieses ist ein ausgegebener \"Text\" bei dem das Wort \"Text\" in Redezeichen ausgegeben werden soll!"; </syntaxhighlight> Hier ermöglicht das escape(Flucht)-Zeichen - oder auch Backslash genannte Zeichen - die vorübergehende Flucht aus dem Quellcode für ein Zeichen, das nicht interpretiert, sondern als normales Char angezeigt wird. Die Ausgabe würde das wie folgt aussehen: Dieses ist ein ausgegebener "Text" bei dem das Wort "Text" in Redezeichen ausgegeben werden soll! ==Sinnvoller Einsatz== <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Datenübergabe]] [[Websiteentwicklung: PHP: Datenübergabe|Zurück zu Datenübergabe]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: $_POST]] [[Websiteentwicklung: PHP: $_POST|Vor zu $_POST]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = $ POST= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: $_POST]] [[Websiteentwicklung: PHP: $_POST|$_POST]] </div> Der Array $_POST enthält den Inhalt von Variablen aus einem anderen Dokument, und nutzt diesen dann in dem vorhandenem Dokument. $PHPVariable = $_POST['Variablenname']; Beispiel: der Radius eines Kreises würde in einem HTML Document in ein Formular eingegeben, das diesen mit der Methode POST an das in dem Attribut Action genannte PHP-Dokument übergibt. In diesem Formular kann der User den Radius des Kreises in ein Textfeld eintragen und diesen durch betätigen des Submitbuttons an das PHP Dokument senden. <syntaxhighlight lang="html4strict"> <!DOCTYPE html> <html> <head><title>Dateneingabe</title></head> <body> <form name="Radiuseingabe" action="kreis.php" method="post"> Bitte den Radius eingeben:<br> <input type="text" name="r"><br> <input type="submit" value="Daten senden" > </form> </body> </html> </syntaxhighlight> Dann wird der Inhalt der Variablen (des Textfeldes) im PHP-Dokument, dessen Code in ein HTML-Grundgerüst eingebettet ist, verarbeitet: <syntaxhighlight lang="html4strict"> <!DOCTYPE html> <head> <title>Verarbeitung und Ausgabe des Ergebnisses</title> </head> <body> </syntaxhighlight> <syntaxhighlight lang="PHP"> <?php // Default-Wert setzen und durch Benutzereingabe überschreiben, falls diese gültig ist $radius = 0; if (isset($_POST['r'])) { // wurde überhaupt ein Wert angegeben… if (is_numeric($_POST['r'])) { // und ist er eine Nummer? if (0 < $_POST['r']) { // und ist der Radius positiv? $radius = $_POST['r']; // dann wird der Wert mit der Methode $_POST übernommen } } } if (0 != $radius) { // die ganze Berechnung soll nur ausgeführt werden, wenn wir eine Eingabe übernommen haben $umfang = 2*$radius*3.14; // Berechnung des Umfangs (2∏r), für ∏ wird 3,14 als Näherungswert genutzt $flaeche = $radius*$radius*pi; // Berechnung der Fläche (r*r*∏), für ∏ wird die (genauere) Funktion pi genutzt ?> Hier kommt das Ergebnis:<br> Der Umfang des Kreises ist: <?php echo $umfang; ?><br> Die Fläche des Kreises ist: <?php echo $flaeche; } else { echo 'Kein gültiger Wert für den Radius r angegeben'; } ?> </syntaxhighlight> <syntaxhighlight lang="html4strict"> </body> </html> </syntaxhighlight> Hierbei ist es von entscheidender Bedeutung, dass sich das Eingabedokument und das verarbeitende PHP-Dokument im selben Verzeichnis auf dem Server befinden, wenn nicht der Pfad angegeben werden soll, sondern im Tag <code>action="Dateiname.php"</code> nur der Dokumentenname stehen soll. <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: $_GET]] [[Websiteentwicklung: PHP: $_GET|Zurück zu $_GET]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Cookies]] [[Websiteentwicklung: PHP: Cookies|Vor zu Cookies]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Cookies= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Cookies]] [[Websiteentwicklung: PHP: Cookies|Cookies]] </div> '''Cookies''' sind kleine Textdateien, die auf dem Computer des Benutzers gespeichert werden. Mithilfe eines Cookies können beispielsweise die Zugangsdaten eines Nutzers auf seinem Rechner hinterlegt werden. Bei einem erneuten Aufruf der Seite, werden diese dann aus dem Cookie gelesen - und der Nutzer so "wieder erkannt". Man sollte hin und wieder dieses Cookies löschen, und von fremden Seiten sollte man das Annehmen von Cookies gänzlich verweigern. Denn da durch kann man zurückverfolgen, auf welchen Seiten man war. Vor allem in Internetcafés muss das beachtet werden. == Cookies mit PHP == In PHP setzt man Cookies mit der Funktion ''setcookie''. Dies muss zwingend im Header-Bereich geschehen. Deshalb muss die Funktion ''setcookie'' vor jeder ''echo''- oder ''print''-Ausgabe erfolgen. Dies gilt auch für Sitzungscookies. Syntax von ''setcookie'': <syntaxhighlight lang="php"> setcookie($cookiename [,$cookiewert [,$verfallszeitpunkt [,$cookiepfad [,$domain [, $sicherheit]]]]); </syntaxhighlight> Der ''$cookiewert'' wird unter dem Namen ''$cookiename'' auf dem PC des Benutzers abgespeichert. Die Information wird solange gespeichert, bis das Skript oder der Benutzer das Cookie löscht oder der ''$verfallszeitpunkt'' erreicht ist. Der Verfallszeitpunkt wird in Sekunden seit dem 1. Januar 1970 (Beginn der UNIX-Epoche) angegeben. Mit der Funktion ''time'' kann man die aktuelle Anzahl der Sekunden seit dem 1. Januar 1970 aufrufen. Der Cookiepfad dient dazu, das Cookie nur bestimmten Unterverzeichnissen zur Verfügung zu stellen. Standardmäßig ist für ''$cookiepfad'' der Wert des Verzeichnisses eingesetzt, den das Cookie gesetzt hat. Der Wert '/' macht das Cookie für alle Verzeichnisse und Unterverzeichnisse verfügbar. Wenn aber zum Beispiel der Wert '/foo/' eingesetzt wird, ist der Cookie nur im Verzeichnis 'foo' und dessen Unterverzeichnissen verfügbar. Mit der Angabe von ''$domain'' kann das Cookie bestimmten Unterdomains zugeordnet werden. ''$sicherheit'' steht normalerweise auf '''FALSE'''. Wird '''TRUE''' angegeben, steht das Cookie nur bei [[http://de.wikipedia.org/wiki/Https HTTPS]]-Verbindungen zur Verfügung. Zu Cookies ein kleines Beispiel: <syntaxhighlight lang="html4strict"> <html> <body> <form action="cookie2.php" method="POST"> Bitte gib deinen Namen ein: <input type="Text" name="name"> <input type="Submit" value="Weiter"> </form> </body> </html> </syntaxhighlight> Dies ist ein kleines Formular mit einem Eingabefeld, in das der Name des Users eingegeben werden soll. Der Name wird dann durch einen Klick auf den Button "Weiter" an die Datei "cookie2.php" gesandt. (siehe dazu auch [[Websiteentwicklung: PHP: Datenübergabe|Datenübergabe]]) Hier die Datei "cookie2.php": <syntaxhighlight lang="php"> <?php if(isset($_POST["name"]) && ! empty($_POST["name"])) { setCookie("name",$_POST["name"],time+2592000); } ?> </syntaxhighlight> In der ersten Zeile wird überprüft, ob eine Variable "name" an das Skript geschickt wurde. Dann wird ein Cookie mit dem Namen "name" gesetzt. In diesem Cookie wird der Name gespeichert, den der User zuvor im Formular eingegeben hat. Dieses Cookie bleibt 2592000 Sekunden erhalten. (Das entspricht in etwa einem Monat) Mit dem folgenden Skript kann man den Inhalt des Cookies wieder ausgeben: <syntaxhighlight lang="php"> <?php if(isset($_COOKIE["name"])) { echo "Hallo ".htmlspecialchars($_COOKIE["name"]).", Du siehst, ich habe deinen Namen nicht vergessen!"; } ?> </syntaxhighlight> == Sitzungscookies == Sitzungscookies verfallen automatisch, wenn der Browser geschlossen wird. Um solche Cookies zu erstellen, lasse einfach den Wert für den Verfallszeitpunkt weg: <syntaxhighlight lang="php"> setCookie("name","Klaus"); </syntaxhighlight> == Cookies per Skript löschen == Cookies können gelöscht werden, indem einfach ein negativer Wert als Verfallszeitpunkt angegeben wird: <syntaxhighlight lang="php"> setCookie("name","",-3600); </syntaxhighlight> <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: $_POST]] [[Websiteentwicklung: PHP: $_POST|Zurück zu $_POST]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Sessions]] [[Websiteentwicklung: PHP: Sessions|Vor zu Sessions]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Sessions= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Sessions]] [[Websiteentwicklung: PHP: Sessions|Sessions]] </div> Sessionvariablen werden benutzt, um Werte übergeordnet zu speichern. Das heißt, wenn ich zum Beispiel einen Userbereich erstelle, kann ich die Daten meines Users auf jeder Seite wieder abrufen. So können Variablen ohne ein Formular „übergeben“ werden. === Beginn einer Session === Vor jeder PHP-Datei in der die Sessionvariablen verwendet werden sollen, ist es nötig die Session zu starten. Dies muss vor jeglichen anderen Ausgaben geschehen, da sonst keine Cookies gesetzt werden können. Sollte ein User im selben Browser auf einer anderen Seite surfen und dann wieder zurückkommen, so ist die Session noch vorhanden. Sessions werden nach einer bestimmten Zeitspanne (einstellbar in der PHP.ini: ''session.gc_maxlifetime'') durch den Garbage-collector entsorgt. <syntaxhighlight lang="php"> <?php //starten der Session session_start; ?> </syntaxhighlight> === Variablen belegen === Die Variablen können genau wie jede andere normale Variable belegt werden. Sie werden mit $_SESSION['beliebiger Name'] benannt. <syntaxhighlight lang="php"> <?php //starten der Session session_start; //belegen einer Variablen $_SESSION['USER_ID'] = 'Wikimeister'; ?> </syntaxhighlight> === Variablen abrufen === Mit dem Namen $_SESSION['beliebiger Name'] lässt sich die Variable jederzeit abrufen sofern die Session gesetzt ist und der Browser nicht geschlossen wurde. <syntaxhighlight lang="php"> <?php //starten der Session session_start; //belegen einer Variablen $_SESSION['USER_ID'] = 'Wikimeister'; //abrufen einer Variablen echo $_SESSION['USER_ID']; ?> </syntaxhighlight> ''Ausgabe:'' Wikimeister === Sessionvariablen löschen === Die Werte, die in der Session gespeichert sind, können auf verschiedene Arten gelöscht werden. ==== Löschen der ganzen Session mittels ''session_destroy;'' ==== <syntaxhighlight lang="php"> <?php //starten der Session session_start; //belegen einer Variablen $_SESSION['USER_ID'] = 'Wikimeister'; //abrufen einer Variablen echo $_SESSION['USER_ID']; //loeschen der session session_destroy; ?> </syntaxhighlight> Anmerkung: Hier werden alle Variablen in der Session bzw. die Session selbst gelöscht. ==== Löschen einzelner Variablen mittels ''unset;'' ==== <syntaxhighlight lang="php"> <?php //starten der Session session_start; //belegen einer Variablen $_SESSION['USER_ID'] = 'Wikimeister'; //abrufen einer Variablen echo $_SESSION['USER_ID']; //löschen der Variablen unset($_SESSION['USER_ID']); ?></syntaxhighlight> == Weiterführende Weblinks == * [http://www.mywebsolution.de/workshops/1/show_Sessions-in-PHP.html PHP Sessions erklärt] <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Cookies]] [[Websiteentwicklung: PHP: Cookies|Zurück zu Cookies]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: OOP]] [[Websiteentwicklung: PHP: OOP|Vor zu Einführung in die Objektorientierte Programmierung]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = OOP= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: OOP]] [[Websiteentwicklung: PHP: OOP|OOP]] </div> == Was ist OOP? == OOP bedeutet ''Objektorientiertes Programmieren'', was aber wohl noch nicht den gewünschten "Aha"-Effekt hervorrufen sollte. Was ist also ein Objekt? Objekte helfen uns, Abbildungen der Wirklichkeit in der Programmiersprache zu realisieren. In OOP werden ähnliche Gegenstände als ''Klassen'' zusammengeführt und Objekte als ''Instanzen'' dieser Klassen erzeugt: Alle Hunde sind somit Instanzen der Klasse „Hund“, alle Häuser Instanzen der Klasse „Haus“ usw. Nehmen wir unseren Freund, den Baum: Bäume sehen in der Regel alle gleich aus: Sie sind groß, grün und werfen Schatten (das nennt man die ''Eigenschaften'' (engl. properties) der Klasse). Einige davon sind nicht mehr allzu gesund, andere sind so arrogant und wollen unterschieden haben, ob sie Eiche, Esche oder Kastanie sind. Nun wissen wir aus der Fantasy-Literatur (z.B. T. A. Barron oder J.R.R Tolkien), dass es möglich ist mit Bäumen zu kommunizieren (und sie zu fragen, ob sie nun Eiche, Esche, Kastanie; groß, klein, gesund oder tot sind; wie sie heißen). Gehen wir von einem Helden Foo aus, der mit dem Baum Bar kommuniziert. Formal heißt das, dass Foo eine Instanz der Klasse "Held" ist, und Bar eine Instanz der Klasse "Baum". Aber irgendwie können die beiden noch nicht wirklich viel tun, was fehlt, sind ''Methoden'' (engl. Method). Fragt Foo also Bar nach seinem Wohlbefinden, ruft er eine Methode von Bar auf, und Bar muss zurückliefern, wie gesund er ist. Im Laufe des Kapitels OOP in PHP werden wir immer wieder auf das Beispiel mit dem Baum zurückkommen. Hier mal eine kleine Aussicht, wie unsere Klasse später aussehen wird: {| style="background:#ddddff; margin-top:2em;margin-bottom:2em;width:100%;" |-- | style="text-align:center;" |'''Hinweis'''<br/><hr/> |-- | style="text-align:center;" |Dieses und alle folgenden Beispiele funktionieren erst ab PHP-Version 5. Die Vorgängerversion PHP 4 bietet zwar auch Objektorientierung, kennt aber viele der vorgestellten Möglichkeiten, wie Sichtbarkeit, Interfaces oder automatische Übergabe von Objekten als Referenz nicht. |} <syntaxhighlight lang="php"> <?php class Baum { protected $gesundheit = 100; // bei 0 ist unser Baum ein Tisch protected $hoehe; // die Höhe des Baumes public function sage_mir_dein_wohlbefinden { if ( $this->gesundheit > 80 ) return 'Mir geht es super.'; if ( $this->gesundheit > 40 ) return 'Ich hatte schon bessere Tage.'; if ( $this->gesundheit > 0 ) return 'Mir geht es echt mies.'; return 'Ich bin ein Tisch.'; /* tritt nur ein wenn $this->gesundheit * kleiner oder gleich 0 ist. */ } public function wie_hoch_bist_du { return 'Ich bin ' . $this->getHoehe . ' Meter hoch.'; } public function wachse($summand) { $this->setHoehe($this->getHoehe + $summand); /* eigentlich müsste man überprüfen, ob * $summand es überhaupt wert ist, addiert * zu werden, also ob er ein Zahlwert ist, * oder nicht. Für den Moment soll uns aber * dieser kurze Code genügen.*/ } public function setGesundheit($neueGesundheit) { $this->gesundheit = $neueGesundheit; } public function getHoehe { return $this->hoehe; } protected function setHoehe($neueHoehe) { $this->hoehe = $neueHoehe; } } // Ende von Klasse Baum $Bar = new Baum; // Neues Objekt der Klasse Baum erzeugen $Bar->setGesundheit(75); $Bar->wachse(5); echo $Bar->wie_hoch_bist_du . ' '; $Bar->wachse(10); echo $Bar->sage_mir_dein_wohlbefinden . ' ' . $Bar->wie_hoch_bist_du; ?> </syntaxhighlight> Dieser Code erzeugt folgende Ausgabe: <pre> Ich bin 5 Meter hoch. Ich hatte schon bessere Tage. Ich bin 15 Meter hoch. </pre> Man sollte bemerken, dass jeder Zugriff auf Eigenschaften '''nur''' durch Methoden erfolgt. Man ''könnte'' sie zwar auch von außen ändern (in diesem speziellen Fall allerdings nicht) und wir werden auch noch lernen wie, aber es gibt gute Gründe, sogenannte ''Setter-'' und ''Getter-Methoden'' zu implementieren. == Der Baum kann sprechen == Der Code eben ist natürlich bei weitem noch nicht vollständig, man müsste noch eine Methode zum Aufnehmen von Regen etc. hinzufügen; auch bleibt unser Baum, so wie er jetzt ist, ewiglich gesund. Da unser Held Foo aber alle Bäume in einem winzigen Wald befragen möchte, brauchen wir noch einige andere Bäume. Auch sollten nicht alle gleich ganz gesund sein. === Der Konstruktor === Ein Konstruktor ist die Funktion, die beim Erzeugen eines Objekts aufgerufen wird, sie heißt <code>__construct</code> (Der doppelte Unterstrich weist auf eine [[Websiteentwicklung: PHP: Magische Methoden|Magische Methode]] hin.) In PHP 4 wurde stattdessen der Name der Klasse verwendet. <syntaxhighlight lang="php"> <?php class Baum { protected $gesundheit; // bei 0 ist unser Baum ein Tisch protected $hoehe; // Höhe des Baumes public function __construct($gesundheit = 100, $hoehe = 0) { $this->setGesundheit($gesundheit); $this->setHoehe($hoehe); } // Vorheriger Code } //- Ende der Klasse Baum echo 'Bar: '; $Bar = new Baum(100,0); $Bar->wachse(5); echo $Bar->wie_hoch_bist_du . ' '; $Bar->wachse(10); echo $Bar->sage_mir_dein_wohlbefinden . ' ' . $Bar->wie_hoch_bist_du; echo "\nBor: "; $Bor = new Baum(10,24); echo $Bor->sage_mir_dein_wohlbefinden . ' ' . $Bor->wie_hoch_bist_du; echo "\nBer: "; $Ber = new Baum(0,1); echo $Ber->sage_mir_dein_wohlbefinden . ' ' . $Ber->wie_hoch_bist_du; ?> </syntaxhighlight> Das erzeugt folgende Ausgabe: <pre> Bar: Ich bin 5 Meter hoch. Mir geht es super. Ich bin 15 Meter hoch. Bor: Mir geht es echt mies. Ich bin 24 Meter hoch. Ber: Ich bin ein Tisch. Ich bin 1 Meter hoch. </pre> Foo hat also zwei Bäume und einen Tisch interviewt. <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Funktionen]] [[Websiteentwicklung: PHP: Funktionen|Zurück zu Funktionen]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Eigenschaften]] [[Websiteentwicklung: PHP: Eigenschaften|Vor zu Eigenschaften]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Eigenschaften= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Eigenschaften]] [[Websiteentwicklung: PHP: Eigenschaften|Eigenschaften]] </div> = Eigenschaften = == Unsere erste Klasse == Du hast also gesehen, was das Ziel dieses Kapitels ist: Einen sprechenden Baum zu erschaffen. Das mag jetzt nicht besonders nahe an der Wirklichkeit sein, denn sprechende Bäume sieht man eher selten bei Webanwendungen; aber solche anschaulichen Beispiele können OOP am besten vermitteln. Du kannst jetzt also deine allererste Klasse „Baum“ schreiben: <syntaxhighlight lang="php"> <?php class Baum { } ?> </syntaxhighlight> Wie du siehst, fangen alle Klassen mit dem Schlüsselwort '''class''' an, gefolgt vom Namen der Klasse (es ist übrigens eine gängige Konvention, Klassennamen groß zu schreiben). Die geschweiften Klammern kennst du ja schon von Bedingungen, Schleifen und Funktionen, hier schließen sie den Inhalt der Klasse ein. Es ist außerdem sinnvoll, für jede Klasse eine eigene PHP-Datei zu erstellen, wie du das auch für einen Satz von Funktionen tun würdest. Speichere diese Klasse also in einer Datei, z.B. mit dem Namen "Baum.php" ab. Willst du jetzt in deiner Seite, z.B. "index.php", auf die Klasse Baum zugreifen, bindest du die Datei mit der Funktion ''require_once'' ein: <syntaxhighlight lang="php"> <?php require_once 'Baum.php'; ?> </syntaxhighlight> require_once (bzw. include_once) stellt im Gegensatz zu require (bzw. include) sicher, dass die Datei nicht aus Versehen zweimal eingebunden wird – das ist sehr wichtig, da Klassen und auch Funktionen nicht doppelt beschrieben werden dürfen. Jetzt hast du also eine leere Klasse, die dir als Vorlage für Objekte dient, sozusagen ein Baum-Bauplan. Allerdings fehlt dir noch ein Objekt, das wir jetzt erzeugen werden: == Das Schlüsselwort new == Um ein neues Objekt mit einer Klasse als Vorlage zu erzeugen (man nennt das: „eine Instanz der Klasse Baum erzeugen“), verwenden wir das Schlüsselwort <b>new</b>: <syntaxhighlight lang="php"> <?php require_once 'Baum.php'; $bar = new Baum; ?> </syntaxhighlight> Wie du siehst, hat die Klasse hier Ähnlichkeiten mit einer Funktion, denn ihr Name wird von Klammern gefolgt. Das liegt daran, dass du mit der Erschaffung des Objektes automatisch den Konstruktor der Klasse aufrufst. Da wir keinen Konstruktor definiert haben, brauchst du keine Parameter übergeben, die Klammern bleiben leer. Um zu prüfen, dass du alles richtig gemacht hast, kannst du dir die Struktur deines bisherigen Objektes mit der Funktion ''var_dump'' anzeigen lassen. Ergänze dazu deine "index.php" um folgende Zeile: <syntaxhighlight lang="php"> var_dump($bar); </syntaxhighlight> Du erhältst diese Ausgabe: '''object'''(''Baum'')[1] == Eigenschaften deklarieren == Wie du im Beispielcode im vorherigen Kapitel gesehen hast, besitzt unser Baum zwei Eigenschaften: Er hat eine bestimmte Höhe und Gesundheit. Diese Eigenschaften werden im oberen Teil einer Klasse definiert, ergänze deine Klasse also, dass sie folgende Form annimmt: <syntaxhighlight lang="php"> <?php class Baum { public $hoehe; public $gesundheit; } ?> </syntaxhighlight> Wenn du deinen bisherigen Code nochmal ausgibst, siehst du diesmal folgende Ausgabe: '''object'''(''Baum'')[1] ''public'' 'hoehe' => null ''public'' 'gesundheit' => null Wie erwartet, hat der Baum zwei Eigenschaften, die noch keinen Wert besitzen. Was das Schlüsselwort '''public''' zu bedeuten hat, erfährst du unten im Abschnitt [[#Sichtbarkeit|Sichtbarkeit]]. Du kannst auch bestimmen, dass Standardwerte vergeben werden, z.B. für einen gesunden Keim: <syntaxhighlight lang="php"> public $hoehe = 0.1; public $gesundheit = 100; </syntaxhighlight> Lass dir das Ergebnis anzeigen, und du wirst sehen, dass alle Objekte dieser Klasse mit diesen Standardwerten starten. == Auf Eigenschaften zugreifen == Jetzt haben wir also einen netten Baum mit Namen $bar, wissen aber eigentlich gar nicht, welche Höhe und Gesundheit er hat (der Weg über var_dump ist gemogelt). Wollen wir jedoch mit dem Baum arbeiten, um z.B. sicherzustellen, dass wir nicht zufällig einen Tisch vor uns haben, müssen wir auf seine Werte zugreifen können. Dies geschieht mit Hilfe des Pfeil-Operators (->, also Bindestrich gefolgt vom größer-als-Zeichen). Ersetze die Ausgabe mit var_dump durch folgenden Code <syntaxhighlight lang="php"> echo $bar->hoehe; echo '<br />'; echo $bar->gesundheit; </syntaxhighlight> und du wirst lesen können: <pre> 0.1 100 </pre> Jetzt ist es leider meistens nicht friedlich in Welten, in denen Bäume sprechen können, und gerade kommt unser Held Foo vorbei, der den Keim mit einem Feind verwechselt und zieht ihm eins mit dem Schwert über. Das ist der Gesundheit unseres kleinen Baumes nicht gerade zuträglich. Um das widerzuspiegeln, greifen wir mit dem Pfeil-Operator auf die Eigenschaft $gesundheit zu und reduzieren diese um 30: <syntaxhighlight lang="php"> $bar->gesundheit = $bar->gesundheit - 30; </syntaxhighlight> oder in der [[Websiteentwicklung: PHP: Operatoren#Zuweisungsoperatoren|Kurzschreibweise]]: <syntaxhighlight lang="php"> $bar->gesundheit -= 30; </syntaxhighlight> Später werden wir auch ein Objekt des Helden erzeugen, um den Vorgang eines Schlags mit dem Schwert zu realisieren. == Der Typ-Operator instanceof == Die vorige Situation ist dem Helden natürlich echt peinlich, wenn er nicht einmal harmlose Bäume von Feinden unterscheiden kann. Um ihm etwas unter die Arme zu greifen, fragen wir vorher sicherheitshalber nach, ob es sich um ein Objekt der Klasse „Feind“ handelt. Das können wir mit dem Typ-Operator <b>instanceof</b>: <syntaxhighlight lang="php"> if ($bar instanceof Feind) { // Feind: angreifen $bar->gesundheit = $bar->gesundheit - 30; } else { // Freund: guten Tag sagen echo 'Seid gegrüßt!'; } </syntaxhighlight> Solange sich also alle Feinde brav an die Regeln halten und sich nicht als Baum verkleiden, sollte dem Helden nicht erneut diese Verwechslung unterlaufen. == Klassenkonstanten == Wie Konstanten, die wir global definieren, haben auch Klassen eigene Konstanten, auf die man zugreifen kann. Sie werden mit dem Schlüsselwort '''const''' definiert. Da alle Dinge in unserer Fantasy-Welt reden können (sogar die Tische), erweitern wir unsere Klassendefinition um eine Konstante, die das anzeigt: <syntaxhighlight lang="php"> <?php class Baum { public $hoehe; public $gesundheit; const KANN_REDEN = true; } ?> </syntaxhighlight> Auf Klassenkonstanten kann man sogar zugreifen, wenn noch nicht mal ein Objekt der Klasse existiert. Das ist allerdings auch logisch, denn Konstanten können, wie der Name schon sagt, nicht verändert werden, daher ist es egal, wie das Objekt beschaffen ist. Außerhalb von Objekten greift man auf Konstanten mit dem ''Scope Resolution Operator'' zu (ein doppelter Doppelpunkt). Ersetze deine "index.php" durch folgenden Code: <syntaxhighlight lang="php"> <?php require_once 'Baum.php'; if (Baum::KANN_REDEN == true) { echo 'Ja, kann reden.'; } else { echo 'Schweigt sich aus.'; } ?> </syntaxhighlight> Wenn alles stimmt, sollte als Ausgabe "Ja, kann reden." zu sehen sein. == Sichtbarkeit == Nehmen wir einmal an, unser Baum ist ziemlich schüchtern, und möchte nicht, dass wir ihm seinen Gesundheitszustand von außen ansehen können. Er will diese Information nur auf freiwilliger Basis preisgeben. Dies können wir erreichen, indem wir das Schlüsselwort '''public''' durch '''protected''' ersetzen: <syntaxhighlight lang="php"> <?php class Baum { public $hoehe; protected $gesundheit; } ?> </syntaxhighlight> Versuchen wir jetzt, uns den Gesundheitszustand des Baumes anzusehen: <syntaxhighlight lang="php"> <?php require_once 'Baum.php'; $bar = new Baum; echo $bar->gesundheit; ?> </syntaxhighlight> PHP wird uns mitteilen, dass wir das nicht dürfen: '''Fatal error: Cannot access protected property Baum::$gesundheit''' Das Schlüsselwort '''protected''' verhindert also, dass von außen auf diese Eigenschaft der Klasse zugegriffen werden kann. Es ist uns so nicht möglich, die Gesundheit zu lesen, geschweige denn zu schreiben (wir haben es also mit einem unbesiegbaren Baum zu tun). Damit dies wieder möglich wird, müssen wir entsprechende Methoden implementieren. Wie das geht, erfährst du im nächsten Kapitel. Abschließend noch eine Übersicht über alle drei möglichen Sichtbarkeiten: {| class="wikitable" |- ! Schlüsselwort !! Wirkung |- | '''public''' || Von außen kann auf die Eigenschaft zugegriffen werden. |- | '''protected''' || Die Eigenschaft ist von außen nicht sichtbar und kann auch nicht verändert werden. |- | '''private''' || Wie ''protected'', allerdings werden Eigenschaften nicht vererbt, können also in abgeleiteten Klassen nicht einmal innerhalb des Objektes gelesen oder geschrieben werden. |} {| class="limage" cellpadding="2" style="background-color: #FFF0F8; margin-right: 5%; margin-left: 5%; text-align: left; border: 2px solid #CC3333; -khtml-border-radius: 10px; -o-border-radius: 10px; -webkit-border-radius: 10px; -ms-border-radius: 10px; -moz-border-radius: 10px; border-radius: 10px;" !width=5%| [[Image:Glasbutton Warnung.svg|top|30px|]] |valign="top" align="left"| Es ist sinnvoll, stets '''alle''' Eigenschaften eines Objektes als protected zu deklarieren und nur mit Hilfe von Methoden auf Objekteigenschaften zuzugreifen, selbst wenn diese nichts anderes machen als die Eigenschaft normal zurückzugeben und zu schreiben. Gründe dafür sind u.a.: * Du kannst im Nachhinein den Zugriff auf die Eigenschaft einschränken oder Aktionen beim Verändern der Eigenschaft auslösen, ohne den gesamten Code ändern zu müssen * In der objektorientierten Programmierung entwirft man Klassen in Hinblick auf Schnittstellen ([[Websiteentwicklung: PHP: Interfaces|Interfaces]]), sodass man die Klasse verwenden kann, ohne ihre konkrete Implementierung zu kennen * Bestimmte Entwurfsmuster wie etwa das [[Muster: Decorator|Decorator-Pattern]] oder das [[Muster: Adapter|Adapter-Pattern]] funktionieren nur mit Getter- und Settermethoden In den Beispielen dieses Buches wird allerdings weiterhin direkt auf die Objekteigenschaften zugegriffen, um den Code möglichst gut lesbar zu gestalten. |} == PHP-Dokumentatiton == Folgende Abschnitte der PHP-Dokumentatition wurden in diesem Kapitel behandelt: * [http://de3.php.net/manual/de/language.oop5.basic.php Grundlagen] * [http://de3.php.net/manual/de/language.oop5.properties.php Eigenschaften] * [http://de3.php.net/manual/de/language.oop5.visibility.php Sichtbarkeit] * [http://de3.php.net/manual/de/language.operators.type.php Typ-Operatoren] <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: OOP]] [[Websiteentwicklung: PHP: OOP|Zurück zu Einführung in die Objektorientierte Programmierung]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Methoden]] [[Websiteentwicklung: PHP: Methoden|Vor zu Methoden]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Methoden= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Methoden]] [[Websiteentwicklung: PHP: Methoden|Methoden]] </div> = Methoden = Unsere Klasse Baum hat nun also bestimmte Eigenschaften, auf die wir zugreifen können (je nachdem, welche Sichtbarkeit sie haben). Da der Baum jedoch sprechen soll, braucht er auch die Möglichkeit, irgendetwas zu bewirken. Dies geschieht mithilfe von ''Methoden'': Das sind die Funktionen einer Klasse. == Der Baum beginnt zu sprechen == Wir können unsere Klasse um eine Methode ''sagHallo'' erweitern, um den [[w:Hallo-Welt-Programm|Klassiker aller Programmierbeispiele]] zu implementieren: <syntaxhighlight lang="php"> <?php class Baum { public $hoehe; protected $gesundheit; const KANN_REDEN = true; public function sagHallo { echo 'Hallo Welt!'; } } ?> </syntaxhighlight> Wenn wir jetzt in unserer Indexseite schreiben <syntaxhighlight lang="php"> <?php require_once 'Baum.php'; $bar = new Baum; $bar->sagHallo; ?> </syntaxhighlight> erhalten wir die erwartete Ausgabe <pre> Hallo Welt! </pre> Wie du nebenbei sicher bemerkt hast, gilt die von Eigenschaften bekannte Sichtbarkeit auch für Methoden. == Statische Eigenschaften und Methoden mit self == Nun wollen wir noch sicherstellen, dass der Baum auch wirklich reden kann. Im letzten Kapitel haben wir die Konstante KANN_REDEN eingebaut, die aussagt, ob die Objekte dieser Klasse sprechen können. Um auf Konstanten in der eigenen Klasse zuzugreifen, können wir das Schlüsselwort '''self''' verwenden. Es wird immer dann angewendet, wenn man auf Elemente einer Klasse zugreifen will, für die kein Objekt benötigt wird. Erweitere die Methode '''sagHallo''' also folgendermaßen: <syntaxhighlight lang="php"> public function sagHallo { if (self::KANN_REDEN == true) { echo 'Hallo Welt!'; return true; // zurückgeben, dass der Sprechversuch geklappt hat } else { return false; // Der Baum kann gar nicht reden } } </syntaxhighlight> Die Ausgabe bleibt gleich, da der Baum reden kann. == Objekteigenschaften und -methoden mit $this == Allerdings wollten wir doch die Gesundheit des Baumes anzeigen lassen, und zwar wie im Einführungsbeispiel als praktischen Text. Um auf Eigenschaften und Methoden zuzugreifen, während man sich innerhalb eines Objektes befindet, verwenden wir die Pseudovariable $this. Um also den Baum mitteilen zu lassen, wie es ihm geht, fügen wir die Methode ''sage_mir_dein_wohlbefinden'' in die Klasse Baum ein: <syntaxhighlight lang="php"> class Baum { public $hoehe; protected $gesundheit; const KANN_REDEN = true; public function sagHallo { if (self::KANN_REDEN == true) { echo 'Hallo Welt!'; return true; // zurückgeben, dass der Sprechversuch geklappt hat } else { return false; // Der Baum kann gar nicht reden } } public function sage_mir_dein_wohlbefinden { if ( $this->gesundheit > 80 ) return 'Mir geht es super.'; if ( $this->gesundheit > 40 ) return 'Ich hatte schon bessere Tage.'; if ( $this->gesundheit > 0 ) return 'Mir geht es echt mies.'; return 'Ich bin ein Tisch.'; /* tritt nur ein wenn $this->gesundheit * kleiner oder gleich 0 ist. */ } } </syntaxhighlight> Wie du siehst, greift die Methode mit $this auf ihre eigene Eigenschaft zu. Wenn du jetzt wissen willst, wie es dem Baum geht <syntaxhighlight lang="php"> echo $bar->sage_mir_dein_wohlbefinden; </syntaxhighlight> erhältst du die Ausgabe: Ich bin ein Tisch. Klar, denn wir haben keinen Standardwert definiert, der Baum hat also eine Gesundheit von null (was nicht exakt das Gleiche ist wie 0). Um dem armen Tisch zu helfen, fügen wir noch die Methode ''veraendereGesundheit'' hinzu, um die Eigenschaft Gesundheit zu verändern. <syntaxhighlight lang="php"> public function veraendereGesundheit($wert) { $this->gesundheit += $wert; // Die Gesundheit soll nur von 0 bis 100 gehen if ($this->gesundheit < 0) { $this->gesundheit = 0; } elseif ($this->gesundheit > 100) { $this->gesundheit = 100; } } </syntaxhighlight> Parameter funktionieren hier genauso wie bei Funktionen. Wir können jetzt testweise die Gesundheit erhöhen und senken: <syntaxhighlight lang="php"> <?php require_once 'Baum.php'; $bar = new Baum; $bar->veraendereGesundheit(30); // Gesundheit = 30 echo $bar->sage_mir_dein_wohlbefinden; echo '<br />'; $bar->veraendereGesundheit(30); // Gesundheit = 60 echo $bar->sage_mir_dein_wohlbefinden; echo '<br />'; $bar->veraendereGesundheit(30); // Gesundheit = 90 echo $bar->sage_mir_dein_wohlbefinden; echo '<br />'; $bar->veraendereGesundheit(-100); // Gesundheit = 0 echo $bar->sage_mir_dein_wohlbefinden; ?> </syntaxhighlight> Ausgabe: <pre> Mir geht es echt mies. Ich hatte schon bessere Tage. Mir geht es super. Ich bin ein Tisch. </pre> Somit macht das Objekt eine wunderbare Verwandlung vom Tisch zum selbstbewussten Baum und wieder zurück durch. == Objekte als Referenz – neue Funktion von PHP 5 == Eine tolle Neuerung von PHP 5 ist, dass Objekte standardmäßig immer als Referenz weitergegeben werden. Was bedeutet das? Nehmen wir an, wir haben eine Klasse Welt, die exakt einen Baum enthalten kann (es handelt sich um eine sehr, sehr kleine Welt). Hier ist die Definition der Klasse: <syntaxhighlight lang="php"> <?php class Welt { protected $baum; public function pflanzeBaum($baum) { $this->baum = $baum; } public function setzeBaumhoehe { $this->baum->hoehe = 10; } } ?> </syntaxhighlight> Führen wir nun in der Indexseite diesen Code aus: <syntaxhighlight lang="php"> <?php require_once 'Baum.php'; require_once 'Welt.php'; $bar = new Baum; $welt = new Welt; $bar->hoehe = 5; echo $bar->hoehe; echo '<br />'; $welt->pflanzeBaum($bar); $welt->setzeBaumhoehe; echo $bar->hoehe; ?> </syntaxhighlight> Als Ergebnis erhalten wir <pre> 5 10 </pre> Das liegt daran, dass keine Kopie des Objekts gepflanzt wurde, sondern das Objekt selbst als Referenz übergeben wird. Das ist meistens sowieso das gewünschte Ergebnis, schließlich handelt es sich um den selben Baum, den wir in die Welt einpflanzen. Auch der Zuweisungsoperator = wird immer nur eine Referenz des Objekts zurückgeben. Wünschen wir aber eine Kopie, können wir das Schlüsselwort '''clone''' verwenden: <syntaxhighlight lang="php"> $ber = clone $bar; </syntaxhighlight> == Type Hinting == Spielen wir doch einmal [[w:Matrjoschka|Matrjoschka]] (auch als russische Puppe bekannt) und pflanzen wir anstatt des Baumes eine Welt in eine Welt: <syntaxhighlight lang="php"> <?php require_once 'Baum.php'; require_once 'Welt.php'; $welt = new Welt; $welt2 = new Welt; $welt->pflanzeBaum($welt2); $welt->setzeBaumhoehe; echo $welt2->hoehe; ?> </syntaxhighlight> Eigentlich erwarten wir eine Fehlermeldung, denn schließlich handelt es sich um eine Welt und keinen Baum. Eine Welt hat doch keine „Baumhöhe“! Zur Überraschung liefert uns PHP aber seelenruhig die Ausgabe <pre> 10 </pre> als ob es sich um einen Baum handeln würde. Das liegt daran, dass Eigenschaften, die in Klassen nicht definiert sind (hier die Eigenschaft $hoehe in der Klasse Welt) als sogenannte ''Magic Properties'' zur Laufzeit erzeugt werden. Die Welt hat jetzt eine Eigenschaft $hoehe, wie uns var_dump($welt2) auch zeigt: '''object'''(''Welt'')[2] ''protected'' 'baum' => null ''public'' 'hoehe' => <small>int</small> 10 Wie können wir also verhindern, dass die Welt stur jedes Objekt einpflanzt? Die Antwort lautet ''Type Hinting''. Wir sagen bei Angabe der Parameter in der Methode, die Instanz welcher Klasse das Objekt sein soll: <syntaxhighlight lang="php"> public function pflanzeBaum(Baum $baum) { $this->baum = $baum; } </syntaxhighlight> Wenn wir jetzt den Code ausführen, erhalten wir die gewünschte Fehlermeldung: '''Catchable fatal error: Argument 1 passed to Welt::pflanzeBaum must be an instance of Baum, instance of Welt given''' Type Hinting funktioniert übrigens auch unter Angabe von [[Websiteentwicklung: PHP: Interfaces|Interfaces]]. == PHP-Dokumentation == Folgende Abschnitte der PHP-Dokumentation wurden in diesem Kapitel behandelt: * [http://de3.php.net/manual/en/language.oop5.basic.php The Basics] * [http://de3.php.net/manual/en/language.oop5.cloning.php Object Cloning] * [http://de3.php.net/manual/de/language.oop5.typehinting.php Type Hinting] <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Eigenschaften]] [[Websiteentwicklung: PHP: Eigenschaften|Zurück zu Eigenschaften]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Magische Methoden]] [[Websiteentwicklung: PHP: Magische Methoden|Vor zu Magische Methoden]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Magische Methoden= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Magische Methoden]] [[Websiteentwicklung: PHP: Magische Methoden|Magische Methoden]] </div> = Magische Methoden = Es gibt einige Methoden, die von PHP in speziellen Fällen aufgerufen werden. Jede Klasse besitzt diese automatisch, sie können aber bei der Deklaration auch mit einer neuen Funktionsweise und anderen Parametern überschrieben werden. Diese Methoden werden ''Magic Methods'' genannt. == __construct == Wann immer man ein neues Objekt erzeugt, wird der entsprechende Konstruktor der Klasse aufgerufen. Er wird in der Regel dafür verwendet, Eigenschaften des neuen Objektes festzulegen. Nehmen wir zum Beispiel unsere Welt-Klasse aus dem vorangegangenen Kapitel: Wir haben eine Methode ''setzeBaumhoehe'' implementiert, die nur richtig funktionieren kann, wenn wir vorher einen Baum gepflanzt haben. Deshalb müsste nun vorher überprüft werden, dass sich hinter der Eigenschaft $baum auch eine Instanz der Klasse Baum versteckt. Da alle Methoden der Klasse Welt mit einem Objekt $baum arbeiten, wollen wir der Welt schon beim Entstehungszeitpunkt sagen, welchen Baum sie verwenden soll. Dazu ändern wir die Deklaration zu folgender um: <syntaxhighlight lang="php"> <?php class Welt { protected $baum; public function __construct(Baum $baum) { $this->baum = $baum; } public function setzeBaumhoehe { $this->baum->hoehe = 10; } } ?> </syntaxhighlight> Wie du siehst, haben wir einfach die Methode ''pflanzeBaum'' in ''__construct'' umbenannt. Um nun eine Welt zu erzeugen, verwenden wir folgenden Code: <syntaxhighlight lang="php"> <?php require_once 'Baum.php'; require_once 'Welt.php'; $bar = new Baum; $welt = new Welt($bar); ?> </syntaxhighlight> Wir übergeben unserer Welt also mit der Erzeugung des Objekts den Baum. Natürlich können wir den Baum auch weiterhin optional machen, dazu setzen wir den Parameter $baum im Konstruktor auf den Standardwert null. Allerdings müssten wir nun wieder eine Prüfmethode implementieren, die sicherstellt, dass ein Baum existiert, wenn wir mit ihm arbeiten wollen. Vielleicht wunderst du dich, warum du einen Konstruktor als public definieren musst, schließlich wird der Konstruktor immer bei der Erzeugung des Objekts aufgerufen. Es gibt allerdings einige Spezialfälle, in denen ein Objekt aus der eigenen Klasse heraus erzeugt wird – zum Beispiel im [[Websiteentwicklung:_PHP:_Muster_Singleton|Singleton-Pattern]]. == __destruct == Der Gegenspieler vom Konstruktor ist der Destruktor. Er wird aufgerufen, wenn das Objekt aus dem globalen Speicher gelöscht wird. Erweitern wir die Welt-Klasse um folgende Methode: <syntaxhighlight lang="php"> public function __destruct { echo 'Ein(e) '.__CLASS__.' wurde zerstört!'; } </syntaxhighlight> Wenn du jetzt deinen Code von oben aufrufst, wird ausgegeben: <pre> Ein(e) Welt wurde zerstört! </pre> Das liegt daran, dass bei Beendigung des Skriptes immer die Destruktoren der Objekte aufgerufen werden. Man kann allerdings auch den Destruktor auslösen, indem man das Objekt mittels der Funktion ''unset'' zerstört. Und als dritte Möglichkeit steht der direkte Aufruf der Funktion ''__destruct'' zur Verfügung, bei der allerdings das Objekt nicht gelöscht, sondern lediglich der Code des Destruktors ausgeführt wird. == __call und __callStatic == Methoden müssen noch nicht einmal definiert sein, um aufgerufen zu werden, sie können auch dynamisch zur Laufzeit erzeugt werden (sog. ''Overloading''). Nehmen wir an, wir rufen in unserem Skript die Methode ''drehe_um_winkel'' auf: <syntaxhighlight lang="php"> <?php require_once 'Baum.php'; require_once 'Welt.php'; $ber = new Baum; $welt = new Welt($ber); $welt->drehe_um_winkel(50); ?> </syntaxhighlight> Selbstverständlich erzeugt das eine Fehlermeldung: '''Fatal error: Call to undefined method Welt::drehe_um_winkel''' Allerdings können wir die Magische Methode ''__call'' in die Klasse Welt einfügen, um auf alle Methodenaufrufe zu reagieren, wenn die Methode nicht erreichbar ist: <syntaxhighlight lang="php"> public function __call($name, $arguments) { if (strtolower($name) == 'drehe_um_winkel') { echo 'Und sie dreht sich doch, um den Winkel '. $arguments[0].'!'; } else { throw new Exception('Funktion '.$name.' ist nicht definiert in Klasse '.__CLASS__); } } </syntaxhighlight> Was macht diese Funktion? Nun, wird eine Methode aufgerufen, die nicht erreichbar ist (also z.B. eine als protected deklarierte Methode von außerhalb aufgerufen, oder eine, die in der Klasse nicht existiert), wird die Magische Methode ''__call'' aufgerufen, mit dem Namen dieser nicht erreichbaren Methode $name sowie deren Parameter als Array $arguments. In diesem Beispiel wird, sofern man versucht, die Methode ''drehe_um_winkel'' aufzurufen, eine Nachricht inklusive des ersten Arguments ausgegeben, ansonsten eine Exception geworfen (mehr zu Exceptions im [[Websiteentwicklung: PHP: Exceptions|entsprechenden Kapitel]]). Als Pendant zu Objektmethoden können auch statische Methoden dynamisch erzeugt werden, dazu wird die Magische Methode ''__callStatic'' aufgerufen, diese muss logischerweise auch als statisch deklariert werden. Mehr zu statischen Methoden findest du im Kapitel [[Websiteentwicklung: PHP: Statische Eigenschaften und Methoden|Statische Eigenschaften und Methoden]]. Dynamisch erzeugte Methoden solltest du nur in ganz speziellen Bedarfsfällen erzeugen. Es ist immer besser, wirkliche Methoden zu implementieren, anstatt sich über Kontrollstrukturen zu behelfen. So muss man bei dynamischen Methoden Elemente wie Sichtbarkeit, Type Hinting oder Überprüfung auf richtige Anzahl der Parameter selbst programmieren. == __get, __set, __isset und __unset == Es gibt entsprechende Magische Methoden zum Overloading auch für nicht erreichbare Klasseneigenschaften. So kann man z.B. eine Eigenschaft als array deklarieren und mit den magischen Methoden $objekt->eigenschaft in $objekt->array[$eigenschaft] übersetzen. Eine Übersicht über diese Methoden liefert die folgende Tabelle: {| class="wikitable" |- ! Methodensignatur !! wird aufgerufen, wenn eine nicht erreichbare Eigenschaft... !! Parameter und Hinweise |- | void __set (string $name, mixed $value) || ...auf einen Wert gesetzt werden soll || $name = Name der Eigenschaft, $value = zu setzender Wert |- | mixed __get (string $name) || ...gelesen werden soll || $name = Name der Eigenschaft |- | bool __isset (string $name) || ...als Parameter der Funktionen ''isset'' oder ''unset'' verwendet wird || $name = Name der Eigenschaft; Methode muss '''true''' oder '''false''' zurückgeben |- | __unset (string $name) || ...als Parameter der Funktion ''unset'' verwendet wird || $name = Name der Eigenschaft |- |} == __sleep und __wakeup == Objekte (und auch andere Daten) können, z.B. um sie zu speichern, mittels der Funktion ''serialize'' in einen besonderen String umgewandelt werden, der mit der Funktion ''unserialize'' wieder in die Ursprungsform verwandelt wird. Damit man vorher nochmal „aufräumen“ kann, gibt es die Magische Methode ''__sleep''. Sie muss ein Array zurückgeben, das die Namen der Eigenschaften des Objekts beinhaltet, die von ''serialize'' gespeichert werden sollen. Unser Baum etwa soll sich immer wieder regenerieren, wenn er zu Bett geht (also serialisiert wird). Daher brauchen wir seine Gesundheit gar nicht speichern: <syntaxhighlight lang="php"> public function __sleep { return array('hoehe'); } </syntaxhighlight> Jetzt setzen wir noch die Gesundheit nach dem Aufwachen auf 100: <syntaxhighlight lang="php"> public function __wakeup { $this->gesundheit = 100; } </syntaxhighlight> Und schon haben wir einen erholten Baum: <syntaxhighlight lang="php"> <?php require_once 'Baum.php'; $ber = new Baum; $speicher = serialize($ber); $ber = unserialize($speicher); echo $ber->sage_mir_dein_wohlbefinden; ?> </syntaxhighlight> <pre> Mir geht es super. </pre> == __toString == Mit der Magischen Methode ''__toString'' können wir kontrollieren, wie sich ein Objekt verhält, das in den Datentyp String konvertiert werden soll, beispielsweise bei Verwendung der Funktion ''strlen'': <syntaxhighlight lang="php"> class Welt { protected $name; protected $baum; public function __construct(Baum $baum, $name = 'Erde') { $this->baum = $baum; $this->name = $name; } public function __toString { return $this->name; } // Restliche Methoden </syntaxhighlight> Nach Erzeugung eines entsprechenden Objektes ohne Angabe eines Namens wird uns die Funktion ''strlen($welt)'' die Zeichenanzahl 4 zurückgeben, da sie auf den String $name verwiesen wird, der "Erde" enthält. == __set_state == == __clone == Nun genügt uns eine Welt nicht, wir wollen noch eine zweite Welt erschaffen, die genauso wie die erste aussieht. Dazu können wir, wie im Kapitel [[Websiteentwicklung: PHP: Methoden#Objekte als Referenz – neue Funktion von PHP 5|Methoden]] gezeigt, das Schlüsselwort '''clone''' verwenden: <syntaxhighlight lang="php"> <?php require_once 'Baum.php'; require_once 'Welt.php'; $ber = new Baum; $welt = new Welt($ber); $welt2 = clone $welt; $welt2->setzeBaumhoehe(10); echo $ber->hoehe; ?> </syntaxhighlight> Als Ausgabe erhalten wir <pre> 10 </pre> denn durch '''clone''' wird eine sogenannte ''flache Kopie'' erzeugt, d.h. wir haben zwar zwei Objekte der Klasse Welt, die teilen sich aber per Referenz dieselbe Instanz von Baum. Der Baum steht also zur gleichen Zeit auf zwei verschiedenen Welten. Da wir nicht Quantenphysik betreiben wollen, ändern wir dieses Verhalten: <syntaxhighlight lang="php"> // Vorhergehender Code der Klasse Welt public function __clone { $this->baum = clone $this->baum; } </syntaxhighlight> Nun wird nach dem Klonen die Funktion ''__clone'' aufgerufen und das Objekt $baum ebenfalls kopiert, somit haben wir eine ''tiefe Kopie'' erzeugt. == __invoke (PHP 5.3) == Die Magische Methode ''__invoke'' ist neu mit der PHP-Version 5.3 hinzugekommen. Hier kann man das Verhalten eines Objektes bestimmen, das wie eine Funktion aufgerufen wird: <syntaxhighlight lang="php"> class Ausgabe { public function __invoke($text) { echo $text; } $ausgabe = new Ausgabe; $ausgabe('Hallo Welt!'); </syntaxhighlight> Ausgabe: <pre> Hallo Welt! </pre> Aufrufbare Objekte geben '''true''' zurück, wenn man auf sie die Funktion ''is_callable'' anwendet. == PHP-Dokumentation == Folgende Abschnitte der PHP-Dokumentation wurden in diesem Kapitel behandelt: * [http://de3.php.net/manual/de/language.oop5.magic.php Magische Methoden] * [http://de3.php.net/manual/de/language.oop5.decon.php#language.oop5.decon.destructor Konstruktoren und Destruktoren] * [http://de3.php.net/manual/de/language.oop5.cloning.php Objekte klonen] <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Methoden]] [[Websiteentwicklung: PHP: Methoden|Zurück zu Methoden]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Statische Eigenschaften und Methoden]] [[Websiteentwicklung: PHP: Statische Eigenschaften und Methoden|Vor zu Statische Eigenschaften und Methoden]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Statische Eigenschaften und Methoden= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Statische Eigenschaften und Methoden]] [[Websiteentwicklung: PHP: Statische Eigenschaften und Methoden|Statische Eigenschaften und Methoden]] </div> = Statische Eigenschaften und Methoden = Bisher mussten wir immer ein Objekt erzeugen, um auf dessen Eigenschaften und Methoden zuzugreifen. Das ist bei statischen Eigenschaften und Methoden anders: Sie können bereits aufgerufen werden, wenn die Klasse deklariert wurde. == Statische Eigenschaften == Wir legen unsere ziemlich angewachsene Klasse Baum für einen Moment zur Seite (werden sie aber im Kapitel [[Websiteentwicklung: PHP: Vererbung|Vererbung]] wieder aufgreifen) und basteln uns eine neue Klasse Apfel: <syntaxhighlight lang="php"> <?php class Apfel { public static $anzahl_aepfel = 0; public $farbe; public function __construct($farbe) { self::$anzahl_aepfel++; $this->farbe = $farbe; } } ?> </syntaxhighlight> Wir haben hier $anzahl_aepfel durch Angabe des Schlüsselwortes '''static''' als statische Eigenschaft deklariert. Im Gegensatz zu normalen Objekteigenschaften und -methoden werden statische Eigenschaften und -methoden mit dem Scope Resolution Operator aufgerufen (wie auch Konstanten), innerhalb einer Klasse wird auf sich selbst mit „self“ verwiesen. Um statische Eigenschaften von Konstanten trennen zu können, muss außerdem das Dollarzeichen verwendet werden. Wie du außerdem siehst, sind statische Eigenschaften entgegen ihrem Namen veränderbar. Nun wollen wir den Code ausprobieren. Verwende dazu folgende 'index.php': <syntaxhighlight lang="php"> <?php require_once 'Apfel.php'; $apfelkorb = new Apfel('rot'); $apfelkorb = new Apfel('gelb'); $apfelkorb = new Apfel('gruen'); echo Apfel::$anzahl_aepfel; ?> </syntaxhighlight> Auf eine statische Eigenschaft greifen wir per Klassenname zu. Als Ausgabe erhältst du das erwartete Ergebnis (3). Dennoch handelt es sich um drei verschiedene Äpfel, wie ''var_dump($apfelkorb)'' zeigt. Statische Eigenschaften kann man also gut mit globalen Variablen vergleichen, sie sind vom Objekt unabhängig. == Statische Methoden == Statische Methoden werden analog zu statischen Eigenschaften deklariert. Implementieren wir also einen Getter für die statische Eigenschaft $anzahl_aepfel <syntaxhighlight lang="php"> <?php class Apfel { protected static $anzahl_aepfel = 0; // Protected, weil nicht jeder darauf direkt zugreifen soll, sondern nur über Getter- bzw. //Setter-Funktion, die in diesem Beispiel fehlt und somit eine Veränderung von Außen ausschliesst public $farbe; public function __construct($farbe) { self::$anzahl_aepfel++; $this->farbe = $farbe; } public static function getAnzahl_aepfel { return self::$anzahl_aepfel; } } </syntaxhighlight> und rufen diese Methode auf: <syntaxhighlight lang="php"> <?php require_once 'Apfel.php'; $apfelkorb = new Apfel('rot'); $apfelkorb = new Apfel('gelb'); $apfelkorb = new Apfel('gruen'); echo Apfel::getAnzahl_aepfel; ?> </syntaxhighlight> Dies führt zur gleichen Ausgabe. == Variable Klassennamen bei statischen Aufrufen (PHP 5.3) == Ab PHP-Version 5.3 können statische Aufrufe auch mit einem variablen Klassennamen geschehen. Folgender Aufruf wäre äquivalent zum obigen Beispiel: <syntaxhighlight lang="php"> <?php require_once 'Apfel.php'; $apfelkorb = new Apfel('rot'); $apfelkorb = new Apfel('gelb'); $apfelkorb = new Apfel('gruen'); $name = 'Apfel'; echo $name::getAnzahl_aepfel; ?> </syntaxhighlight> == Späte statische Bindung (PHP 5.3) == Ebenfalls neu seit PHP-Version 5.3 ist die späte statische Bindung („Late static binding“). [[Websiteentwicklung: PHP: Vererbung|Erbt]] eine Klasse von einer anderen, wird der Kontext von self normalerweise auf die Vaterklasse angewendet. Ein Beispiel: <syntaxhighlight lang="PHP"> <?php class A { protected static function begruessung { return 'Hallo!'; } public static function sagHallo { echo self::begruessung; } } class B extends A { protected static function begruessung { return 'Seid gegrüßt!'; } } B::sagHallo; ?> </syntaxhighlight> Dies erzeugt die Ausgabe <pre> Hallo! </pre> da das Schlüsselwort self in dem Kontext aufgelöst wird, in dem es definiert ist. Soll dagegen der Kontext verwendet werden, in dem self aufgerufen wird, verwendet man das Schlüsselwort static anstatt self: <syntaxhighlight lang="PHP"> <?php class A { protected static function begruessung { return 'Hallo!'; } public static function sagHallo { echo static::begruessung; } } class B extends A { protected static function begruessung { return 'Seid gegrüßt!'; } } B::sagHallo; ?> </syntaxhighlight> <pre> Seid gegrüßt! </pre> == Singleton-Pattern == Einen praktischen Einsatz von statischen Eigenschaften und Methoden zeigt das [[Websiteentwicklung: PHP: Muster Singleton|Singleton-Pattern]], welches sicherstellt, dass nur eine Instanz einer Klasse vorhanden ist und global darauf zugegriffen werden kann. == PHP-Dokumentation == Folgende Abschnitte der PHP-Dokumentation wurden in diesem Kapitel behandelt: * [http://de3.php.net/manual/de/language.oop5.static.php Static-Schlüsselwort] * [http://de3.php.net/manual/de/language.oop5.late-static-bindings.php Späte statische Bindung] <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Magische Methoden]] [[Websiteentwicklung: PHP: Magische Methoden|Zurück zu Magische Methoden]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Vererbung]] [[Websiteentwicklung: PHP: Vererbung|Vor zu Vererbung]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Vererbung= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Vererbung]] [[Websiteentwicklung: PHP: Vererbung|Vererbung]] </div> = Vererbung = Eine der wichtigsten Möglichkeiten von Klassen (wenn nicht DIE wichtigste) ist die ''Vererbung''. Damit können Klassen auf anderen Klassen aufbauen, sie erben alle Eigenschaften und Methoden der Elternklasse. Schauen wir uns dazu noch einmal unsere bisherige Klasse „Baum“ an: <syntaxhighlight lang="php"> class Baum { public $hoehe; protected $gesundheit; const KANN_REDEN = true; public function sagHallo { if (self::KANN_REDEN == true) { echo 'Hallo Welt!'; return true; // zurückgeben, dass der Sprechversuch geklappt hat } else { return false; // Der Baum kann gar nicht reden } } public function sage_mir_dein_wohlbefinden { if ( $this->gesundheit > 80 ) return 'Mir geht es super.'; if ( $this->gesundheit > 40 ) return 'Ich hatte schon bessere Tage.'; if ( $this->gesundheit > 0 ) return 'Mir geht es echt mies.'; return 'Ich bin ein Tisch.'; /* tritt nur ein wenn $this->gesundheit * kleiner oder gleich 0 ist. */ } } </syntaxhighlight> == Das Schlüsselwort extends == Vererbung geschieht in PHP mittels des Schlüsselworts '''extends''': <syntaxhighlight lang="php"> class Kastanie extends Baum { } $kastanie = new Kastanie; echo $kastanie->sage_mir_dein_wohlbefinden; </syntaxhighlight> Ausgabe: <pre> Ich bin ein Tisch. </pre> Wie du siehst, hat die Kastanie alle Methoden der Klasse Baum geerbt. == Überschreiben von Methoden und Eigenschaften == Eigenschaften können von der Kindklasse auch überschrieben und so mit neuen Werten belegt werden: <syntaxhighlight lang="php"> class Kastanie extends Baum { protected $gesundheit = 100; } $kastanie = new Kastanie; echo $kastanie->sage_mir_dein_wohlbefinden; </syntaxhighlight> <pre> Mir geht es super. </pre> Genau so können Methoden ebenfalls überschrieben werden, beispielsweise, weil unsere Kastanie unhöflich ist und niemals Hallo sagt: <syntaxhighlight lang="php"> class Kastanie extends Baum { protected $gesundheit = 100; public function sagHallo($sender) { echo 'Erzähler: ' . $sender . ' erhält keine Antwort von ' . get_class($this); } } $kastanie = new Kastanie; $kastanie->sagHallo('Foo'); </syntaxhighlight> So können auch neue Parameter der Methode hinzugefügt werden, in diesem Falle ist es der Name desjenigen, der die Kastanie begrüßt. == Form der Vererbung == PHP kann keine [[w:Mehrfachvererbung|Mehrfachvererbung]], d.h., eine Klasse kann immer nur von einer einzigen Klasse abgeleitet werden. Allerdings kannst du Vererbungen aneinander ketten: <syntaxhighlight lang="php"> class Rosskastanie extends Kastanie { } </syntaxhighlight> Somit ist die Vererbungssequenz: Baum => Kastanie => Rosskastanie. Selbstverständlich kann aber eine Elternklasse mehrere Kinder haben: <syntaxhighlight lang="php"> class Buche extends Baum; class Esche extends Baum; // ... </syntaxhighlight> == Type Hinting und Vererbung == Abgeleitete Klassen erfüllen Type Hints der Elternklasse. Die Methode <syntaxhighlight lang="php"> public function __construct(Baum $baum) { $this->baum = $baum; } </syntaxhighlight> in der Klasse Welt kann auch mit einer Rosskastanie gültig aufgerufen werden: <syntaxhighlight lang="php"> $kastanie = new Rosskastanie; $welt = new Welt($kastanie); </syntaxhighlight> == Auf überschriebene Methoden zugreifen == Überschriebene Methoden werden zwar vollständig von der neuen Methode ersetzt, allerdings kann noch auf sie zugegriffen werden. Nehmen wir an, unser neuester Zuwachs bei den Bäumen ist ein Spiegelbaum, der außer "Hallo" alles rückwärts sagt. Natürlich muss er dann auch die Sätze der Methode ''sage_mir_dein_wohlbefinden'' rückwärts aussprechen. Wir könnten jetzt hingehen und in eine überschreibende Methode diese Funktion (mittels ''strrev'') einbauen: <syntaxhighlight lang="php"> class Spiegelbaum extends Baum { public function sage_mir_dein_wohlbefinden { if ( $this->gesundheit > 80 ) return strrev('Mir geht es super.'); if ( $this->gesundheit > 40 ) return strrev('Ich hatte schon bessere Tage.'); if ( $this->gesundheit > 0 ) return strrev('Mir geht es echt mies.'); return strrev('Ich bin ein Tisch.'); /* tritt nur ein wenn $this->gesundheit * kleiner oder gleich 0 ist. */ } } </syntaxhighlight> Das widerspricht aber guter Klassenmodellierung, denn wir mussten die komplette Logik kopieren. Was ist denn, wenn jetzt noch ein neuer Satz eingefügt werden soll, z.B. bei der Bedingung "Gesundheit > 100"? Wir müssten sowohl die Klasse Baum als auch die Klasse Spiegelbaum anpassen. Da hätten wir uns die Vererbung auch gleich ganz sparen können! Zum Glück kennt PHP das Schlüsselwort '''parent'''. Damit wird ermöglicht, auf Methoden der Elternklasse zuzugreifen. Gefolgt wird parent vom Scope Resolution Operator, weil die Methode nicht wirklich dem Objekt angehört, sondern sich nur in der Klasseninformation der Elternklasse befindet. So sieht dann die Klasse Spiegelbaum aus: <syntaxhighlight lang="php"> class Spiegelbaum extends Baum { public function sage_mir_dein_wohlbefinden { return strrev(parent::sage_mir_dein_wohlbefinden); } } </syntaxhighlight> {| class=limage cellpadding="2" width=90% style=" margin-right: 5%; margin-left: 5%; text-align: left; border:solid #001 2px; -khtml-border-radius: 10px; -o-border-radius: 10px; -webkit-border-radius: 10px; -ms-border-radius: 10px; -moz-border-radius: 10px; border-radius: 10px; " !width=5%|Tipp: [[Bild:Glasbutton_Tipp.svg|100px|]] |valign="top" align="left"| Besonders hilfreich ist diese Möglichkeit bei Objekten, die andere Objekte per Konstruktor in sich kapseln (z.B. der Controller im [[w:Model_View_Controller|MVC-Modell]]), aber davon abgeleitete Klassen auch mehr Objekte haben können: <syntaxhighlight lang="php"> class Controller { protected $model; protected $view; public function __construct(Model $model, View $view) { $this->model = $model; $this->view = $view; } } class WithloggerController extends Controller { protected $logger; public function __construct(Model $model, View $view, Logger $logger) { $this->logger = $logger; parent::__construct($model, $view); } } </syntaxhighlight> |} == Abstrakte Klassen und Methoden == Unsere Klasse Baum ist eigentlich nicht dafür gedacht, einfach so verwendet zu werden. Schließlich gibt es nicht ''den'' Baum, sondern nur die verschiedenen Unterklassen wie Kastanien, Buchen, etc. Der Begriff "Baum" ist doch viel zu abstrakt! Genau das können wir PHP auch sagen, mit dem Schlüsselwort '''abstract''': <syntaxhighlight lang="php"> abstract class Baum { // vorhergehender Code } </syntaxhighlight> Jetzt ist es unmöglich, ein Objekt der Klasse Baum zu erzeugen: ''' Fatal error: Cannot instantiate abstract class Baum''' Zuvor müssen wir also z.B. die Klasse Buche von Baum ableiten: <syntaxhighlight lang="php"> class Buche extends Baum { } </syntaxhighlight> Besonders viel haben wir dadurch allerdings nicht gewonnen. Die Klasse Buche ist im Grunde das gleiche wie die Klasse Baum - alle Methoden und Eigenschaften wurden übernommen. Aber angenommen, die Methode sagHallo soll zwingend überschrieben werden? Dann geht das auch: <syntaxhighlight lang="php"> abstract class Baum { abstract public function sagHallo; // restlicher Code } </syntaxhighlight> Abstrakte Methoden enthalten nur den Methodenkopf, abgeschlossen von einem Semikolon, können also selbst keinen Code enthalten. Klassen, die auch nur eine abstrakte Methode enthalten, müssen ebenfalls als abstrakt definiert werden. Bei Erzeugung einer neuen Buche gibt es nun eine Fehlermeldung: '''Fatal error: Class Buche contains 1 abstract method and must therefore be declared abstract''' '''or implement the remaining methods (Baum::sagHallo)''' PHP sagt dir, welches deine Optionen sind: Entwender du deklarierst die Klasse Buche ebenfalls als abstrakt (könntest dann aber wiederum kein Objekt davon erzeugen), oder du erweiterst diese um die Methode sagHallo. Diese Methode muss exakt den gleichen Methodenkopf haben: <syntaxhighlight lang="php"> class Buche extends Baum { public function sagHallo { echo '"Hallo", sagte die Buche.'; } } </syntaxhighlight> == Finale Klassen und Methoden == Genau so wie festgelegt werden kann, dass Klassen und Methoden überschrieben werden ''müssen'', kann man mit dem Schlüsselwort '''final''' bestimmen, dass die Klasse oder Methode ''nicht'' überschrieben werden darf: <syntaxhighlight lang="php"> class Baum { final public function sage_mir_dein_wohlbefinden { // Inhalt der Methode } } class Buche extends Baum { public function sage_mir_dein_wohlbefinden { return false; } } </syntaxhighlight> Das führt zu einer Fehlermeldung: '''Fatal error: Cannot override final method Baum::sage_mir_dein_wohlbefinden''' Das geht auf die gleiche Weise für Klassen: <syntaxhighlight lang="php"> final class Baum { } class Kastanie extends Baum { } </syntaxhighlight> Auch das ist ein Fehler: '''Fatal error: Class Kastanie may not inherit from final class (Baum)''' == PHP-Dokumentation == Folgende Abschnitte der PHP-Dokumentation wurden in diesem Kapitel behandelt: * [http://www.php.net/manual/de/language.oop5.basic.php Die Grundlagen] * [http://www.php.net/manual/de/language.oop5.abstract.php Klassenabstraktion] * [http://www.php.net/manual/de/language.oop5.final.php Final-Schlüsselwort] <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Statische Eigenschaften und Methoden]] [[Websiteentwicklung: PHP: Statische Eigenschaften und Methoden|Zurück zu Statische Eigenschaften und Methoden]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Interfaces]] [[Websiteentwicklung: PHP: Interfaces|Vor zu Interfaces]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Interfaces= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Interfaces]] [[Websiteentwicklung: PHP: Interfaces|Interfaces]] </div> = Interfaces = Schau dir einmal die folgende Klasse an: <syntaxhighlight lang="php"> class Versammlung { protected $sprecher = array; public function neuerSprecher($sprecher) { $this->sprecher = $sprecher; } public function alleStellenSichVor { foreach ($this->sprecher as $sprecher) { $sprecher->sagHallo; echo '<br />'; } } } </syntaxhighlight> Im Kapitel [[Websiteentwicklung: PHP: Methoden|Methoden]] hatten wir dem Baum die Methode ''sagHallo'' gegeben. Somit können wir folgenden Code problemlos ausführen: <syntaxhighlight lang="php"> $baum = new Baum; $versammlung = new Versammlung; $versammlung->neuerSprecher($baum); $versammlung->alleStellenSichVor; </syntaxhighlight> Jetzt muss allerdings sichergestellt sein, dass alle Objekte, die wir an die Methode ''neuerSprecher'' übergeben, auch sprechen können, denn sonst würden wir Gefahr laufen, eine nicht existierende Methode aufzurufen. Bislang hatten wir das mit einer Notlösung, nämlich einer Konstante, gemacht; dafür sind Konstanten jedoch nicht gedacht. Besser ist die Verwendung eines ''Interface''. == Definition == Ein Interface ("Schnittstelle") kann Konstanten und Methodensignaturen beinhalten. Wenn eine Klasse ein Interface implementiert, muss sie oder die Elternklasse alle Methoden des Interface besitzen. Die Methoden müssen exakt die gleiche Signatur haben, insbesondere die gleichen TypeHints. Im Gegensatz zur Vererbung können Klassen auch mehrere Interfaces implementieren, diese dürfen jedoch keine Methoden mit gleichem Namen haben, da PHP diesen Konflikt nicht auflösen kann. == Einfaches Interface == <syntaxhighlight lang="php"> interface Sprecher { public function sagHallo; } </syntaxhighlight> Unser Baum kann nun dieses Interface mit dem Schlüsselwort '''implements''' implementieren: <syntaxhighlight lang="php"> class Baum implements Sprecher { // restlicher Code } </syntaxhighlight> implements ersetzt hier übrigens nicht extends – Vererbung und die Implementierung von Interfaces können gleichzeitig benutzt werden. Unser Baum ist nun gezwungen, alle Methoden des Interface anzubieten. Da das bereits der Fall ist, wird der Code weiterhin funktionieren. == TypeHinting und instanceof == TypeHinting kann auch für Interfaces verwendet werden: <syntaxhighlight lang="php"> //... public function neuerSprecher(Sprecher $sprecher) { //... </syntaxhighlight> Auch der Operator '''instanceof''' funktioniert mit Interfaces. == Mehrere Interfaces == Nun braucht unsere Versammlung noch einen Vorstand, der die Versammlung eröffnet. Mit ein paar Änderungen sieht unsere Klasse nun so aus: <syntaxhighlight lang="php"> class Versammlung { protected $sprecher = array; protected $vorstand; public function neuerSprecher(Sprecher $sprecher) { $this->sprecher = $sprecher; } public function setzeVorstand(Vorstand $vorstand) { $this->vorstand = $vorstand; } public function alleStellenSichVor { foreach ($this->sprecher as $sprecher) { $sprecher->sagHallo; echo '<br />'; } } public function eroeffnen { $this->vorstand->verleseTagesordnung; } } </syntaxhighlight> Nun brauchen wir das Interface Vorstand, welches die Methode ''verleseTagesordnung'' zwingend vorschreibt: <syntaxhighlight lang="php"> interface Vorstand { public function verleseTagesordnung; } </syntaxhighlight> Zum Schluss erweitern wir noch die Klasse Baum, sodass sie sowohl als Sprecher, wie auch als Vorstand auftritt: <syntaxhighlight lang="php"> class Baum implements Sprecher, Vorstand { //... public function verleseTagesordnung { echo 'Punkt 1: Held Foo zum Ehrenmitglied ernennen. Punkt 2: ...'; } </syntaxhighlight> Jetzt ist die Versammlung bereit, abgehalten zu werden: <syntaxhighlight lang="php"> $baum = new Baum; $versammlung = new Versammlung; $versammlung->neuerSprecher($baum); $versammlung->setzeVorstand($baum); $versammlung->alleStellenSichVor; $versammlung->eroeffnen; </syntaxhighlight> Ausgabe: <pre> Hallo Welt! Punkt 1: Held Foo zum Ehrenmitglied ernennen. Punkt 2: ... </pre> == Interfaces und Vererbung == Interfaces unterstützen ebenfalls die Vererbung. Soll zum Beispiel jeder Vorstand zwingend auch als Sprecher verstanden werden, lässt man das Interface Vorstand vom Interface Sprecher erben: <syntaxhighlight lang="php"> interface Vorstand extends Sprecher { //... </syntaxhighlight> == PHP-Dokumentation == Folgender Abschnitt der PHP-Dokumentation wurde in diesem Kapitel behandelt: * [http://www.php.net/manual/de/language.oop5.interfaces.php Interfaces] <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Vererbung]] [[Websiteentwicklung: PHP: Vererbung|Zurück zu Vererbung]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Autoloading]] [[Websiteentwicklung: PHP: Autoloading|Vor zu Autoloading]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Autoloading= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Autoloading]] [[Websiteentwicklung: PHP: Autoloading|Autoloading]] </div> = Autoloading = Mit einer wachsenden Anzahl an Klassen werden die Aufrufe von ''require_once'' immer häufiger und über das gesamte Projekt verteilt. So brauchen wir, um eine Welt, eine Kastanie und einen Helden zu Erzeugen, diesen Code: <syntaxhighlight lang="php"> <?php require_once 'Kastanie.php'; require_once 'Welt.php'; require_once 'Foo.php'; $baum = new Kastanie; $welt = new Welt($baum); $held = new Foo; </syntaxhighlight> Zudem muss in der Datei "Kastanie.php" auch ein ''require_once'' auf die Elternklasse Baum erfolgen. Wir verstoßen damit aber gegen das Prinzip der [[w:Lose Kopplung|Losen Kopplung]]: Wenn wir jetzt alle unsere Klassen in ein Verzeichnis ''classes'' verschieben (was sinnvoll ist), müssen wir alle unsere Pfade in allen Dateien anpassen. Es wäre doch praktischer, wenn wir PHP mitteilen könnten, sich selbst die Klassendatei zu suchen, wenn die Klassendefinition noch nicht geladen wurde. Genau das funktioniert mittels Autoloading. == Autoload-Funktion == PHP benötigt dafür eine Autoload-Funktion. Diese Funktion hat einen Parameter, die den kompletten Klassen- oder Interfacenamen (inklusive eventuell aufgelöster [[Websiteentwicklung: PHP: Namespaces|Namespaces]]) entgegen nimmt. PHP ruft dann diese Funktion auf, wenn eine Klasse mit noch nicht vorhandener Definition angefordert wird, z.B. durch Erzeugung eines neuen Objektes dieser Klasse oder durch Zugriff auf eine Klassenkonstante. === Der alte Weg === Einen solchen Autoloader kann mit der magischen Funktion ''__autoload'' bereitstellen. <syntaxhighlight lang="php"> <?php function __autoload($klassenname) { $file = 'classes/' . $klassenname . '.php'; if (file_exists($file)) { /** * Wer ausschließlich Autoloading verwendet, kann auf "_once" verzichten, * da die Funktion nur einmal pro Klasse aufgerufen wird. */ require_once $file; } else { return false; } } $held = new Foo; $baum = new Kastanie; //... </syntaxhighlight> PHP wird nun bei der Erzeugung von "Foo" automatisch die Funktion __autoload aufrufen. Diese bindet dann die Datei 'classes/Foo.php', falls existent, ein. Nun wird PHP nochmal versuchen, ein Objekt der Klasse "Foo" zu erzeugen. Gelingt dies immer noch nicht, wird ein Standardfehler angezeigt, dass die Klasse nicht gefunden wurde. Einen großen Nachteil hat die Verwendung von ''__autoload'': Es kann immer nur eine einzige Funktion mit dem Namen ''__autoload'' geben. Man kann damit also keine fremden Pakete verwenden, die ihrerseits ein ''__autoload'' beinhalten. === spl_autoload_register (PHP-Version >= 5.1.2) === Die ''Standard PHP Library'' (SPL) bietet die Möglichkeit, mehrere Autoloader in einem Stapel zu registrieren. Diese werden dann einer nach dem anderen abgearbeitet, bis die Klasse gefunden oder das Ende des Stapels erreicht wurde. Obwohl es möglich ist, ''__autoload'' selbst zu registrieren, sollte man besser eine anders benannte Funktion verwenden. Das kann, wegen des callback-Typs, auch eine Objekt- oder statische Methode sein: <syntaxhighlight lang="php"> <?php // Datei: classes/fantasyAutoloader.php class fantasyAutoloader { public static function load($klassenname) { $file = __DIR__ . DIRECTORY_SEPARATOR . $klassenname . '.php'; if (file_exists($file)) { require_once $file; } else { return false; } } } </syntaxhighlight> <syntaxhighlight lang="php"> <?php // Datei: index.php require_once 'classes/fantasyAutoloader.php'; spl_autoload_register(array('fantasyAutoloader', 'load')); $held = new Foo; //... </syntaxhighlight> Somit können andere Pakete ebenfalls ihre Autoloader mit ''spl_autoload_register'' registrieren. == Lösungen für Verzeichnisbäume == Der oben gezeigte Autoloader funktioniert – solange sich alle Klassen im Verzeichnis "classes" befinden und als Dateinamen den Klassennamen tragen. Es ist jedoch bei großen Projekten nicht unüblich, dass 100 und mehr Klassen geschrieben werden. Diese Klassen möchte man jedoch in eine saubere Verzeichnisstruktur einordnen. So könnten wir alle unsere Baumklassen in das Verzeichnis "classes/Baum/", alle Heldenklassen in das Verzeichnis "classes/Person/Held/" usw. ablegen. Wie können wir aber nun dem Autoloader mitteilen, dass er genau in diesem Verzeichnis nach der Klasse "Foo" suchen soll? ''Keine'' Lösung wäre es, bei jedem Autoloading alle Verzeichnisse zu durchsuchen, denn Dateisystemoperationen sind ressourcenintensiv. Mit der Zeit haben sich verschiedene Lösungen etabliert, die hier kurz vorgestellt werden: === Pfad im Klassennamen === Das ist die am weitesten verbreitete Lösung (sie wird beispielsweise vom Zend-Framework verwendet). Alle Klassen tragen ihren Pfad, durch Unterstriche getrennt, im Klassennamen. Unser Held hätte dann folgende Definition (vorausgesetzt, er erbt von einer abstrakten Heldenklasse): <syntaxhighlight lang="php"> <?php class Person_Held_Foo extends Person_Held_Abstract { //... } </syntaxhighlight> Dementsprechend funktioniert der Autoloader so: <syntaxhighlight lang="php"> <?php function pfadImKlassennamen($klassenname) { $ordner = explode('_', $klassenname); $file = 'classes/' . implode('/', $ordner) . '.php'; if (file_exists($file)) { require_once $file; } else { return false; } } </syntaxhighlight> Diese Methode hat allerdings auch einen Nachteil: Die Klassennamen wachsen zu unnatürlichen, schwer lesbaren Gebilden heran. Spätestens bei "Service_HTTP_Request_POST_Parameter_Option" sollte man diese Lösung überdenken. === Pfad im Namespace === Mit der Version 5.3 wurden in PHP die [[Websiteentwicklung: PHP: Namespaces|Namespaces]] eingeführt. Sie verhindern Überschneidungen in der Benennung von Klassen und bieten sich durch ihre Pfadstruktur geradezu für das Autoloading an: <syntaxhighlight lang="php"> <?php namespace org\wikibooks\de\PHP; function pfadImNamespace($klassenname) { if (0 !== strpos($klassenname, __NAMESPACE__)) { // Dieser Autoloader ist für diesen Namespace nicht zuständig return false; } $sub_namespace = substr($klassenname, strlen(__NAMESPACE__)); $teile = explode('\\', $sub_namespace); $file = implode(DIRECTORY_SEPARATOR, $teile) . '.php'; if (file_exists($file)) { require_once $file; } else { return false; } } </syntaxhighlight> === Generierte Liste der Klassen === Die beiden oben vorgestellten Lösungen erfordern wieder eine genaue Kenntnis der Verzeichnisstruktur, da sie entweder im Namespace oder im Klassennamen abgebildet wird. Verschiebt man eine Klasse, muss man diese in jeder Verwendung umbenennen. Dieser Nutzen von Autoloading geht somit wieder verloren. Eine weitere Lösung besteht darin, die Pfade aller Klassen und Interfaces im Projekt in einem Array zu speichern: <syntaxhighlight lang="php"> <?php function generierterAutoloader($klassenname) { static $klassen = array ('Foo' => 'classes/Helden/Foo.php', 'Kastanie' => 'classes/Baeume/Kastanie.php', 'AlternativerDateiname' => 'classes/alternativ.class.php'); if (!isset($klassen[$klassenname])) return false; require_once $klassen[$klassenname]; } </syntaxhighlight> Das Schlüsselwort '''static''' sorgt dafür, dass das Array, unabhängig von der Zahl der Funktionsaufrufe, nur einmal pro Aufruf erzeugt wird, und das bereits bei der Kompilierung, was einen zusätzlichen Geschwindigkeitsvorteil bedeutet. Die Pfade zu den Klassen muss man nicht von Hand eintragen. Es bietet sich an, ein Skript zu schreiben, das ein gegebenes Verzeichnis nach Klassen und Interfaces durchsucht und einträgt. Wenn du magst, kannst du das als Übung einmal versuchen. Du brauchst Verzeichnisfunktionen, Rekursion und die Funktion [http://de3.php.net/manual/de/function.token-get-all.php ''token_get_all'']. Alternativ kannst du auf eine der zahlreichen fertigen Umsetzungen zurückgreifen. Der Vorteil dieser Methode ist die Rückkehr zu verständlichen Klassennamen bzw. die Unabhängigkeit von Namespace und Pfad, Nachteil der zwingende Aufruf des Generators für neue Klassen und Interfaces. == PHP-Dokumentation == Folgende Abschnitte der PHP-Dokumentation wurden in diesem Kapitel behandelt: * [http://de.php.net/manual/de/language.oop5.autoload.php Autoloading] * [http://de.php.net/manual/de/function.spl-autoload-register.php spl_autoload_register] <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Interfaces]] [[Websiteentwicklung: PHP: Interfaces|Zurück zu Interfaces]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Traits]] [[Websiteentwicklung: PHP: Traits|Vor zu Traits]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Traits= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Traits]] [[Websiteentwicklung: PHP: Traits|Traits]] </div> = Traits = Ein Trait hat Ähnlichkeiten mit einer Klasse. Man kann diesen allerdings nicht instantiieren. Ein Trait wird benutzt um eine Menge an Methoden in mehreren voneinander unabhängigen Klassen zu benutzen. Der Trait verhindert somit Probleme die entstehen können durch Mehrfachvererbung. <syntaxhighlight lang="php"> trait Hallo { public function sagHallo { echo 'Hallo Welt!'; } } class Klasse1 { use Hallo; public function sagMehr { echo ' In Klasse 1'; } } class Klasse2 { use Hallo; public function sagMehr { echo ' In Klasse 2'; } } $o = new Klasse1; $o->sagHallo; $o->sagMehr; $u = new Klasse2; $u->sagHallo; $u->sagMehr; </syntaxhighlight> Ausgabe: <pre> Hallo Welt! In Klasse 1 Hallo Welt! In Klasse 2 </pre> Der Trait definiert eine Funktion die wir mit dem Keyword "use" in eine Klasse integrieren können. Der Trait ist in beliebig vielen Klassen einsetzbar und erlaubt so eine horizontale Wiederverwendung des Codes (engl. horizontal reuse). Es können auch mehrere Traits in einer Klasse verwendet werden, dazu werden die Traits in der "use" Anweisung per Komma getrennt: <syntaxhighlight lang="php"> use Hallo, Welt; </syntaxhighlight> Zu beachten in Verbindung mit Namespaces wäre: Der use Operator außerhalb von Klassen für Namespaces sieht seine Argumente immer als absolut an, der use Operator für Traits beachtet den vorherigen use Operator für Namespaces und ist somit relativ. Die Methoden der aktuellen Klasse überschreiben die Methoden des Traits. Die Methoden des Traits überschreiben aber die Methoden, die die aktuelle Klasse von einer Vaterklasse geerbt hat. == Weitere Möglichkeiten mit use == Durch eine "use" Anweisung kann man ebenfalls die folgenden Dinge machen: === Konfliktauflösung === <syntaxhighlight lang="php"> trait Foo { public function sayName { echo 'Foo'; } } trait Bar { public function sayName { echo 'Bar'; } } class Talker { use Foo, Bar { Foo::sayName insteadof Bar; Bar::sayName as sayBarName; } } </syntaxhighlight> Hier haben beide Traits eine Methode mit gleichem Namen, um beide Traits zu implementieren, muss man sich nun eine dieser Methoden aussuchen mit dem Schlüsselwort "insteadof". Danach kann man allerdings der hier ausgeschlossenen Methode einen Alias geben mit dem Schlüsselwort "as". Im oberen Beispiel haben wir also nun 2 Methoden: sayName ruft die Funktion im Trait Foo auf und sayBarName ruft die Funktion sayName im Trait Bar auf. Der Alias ist hier allerdings optional, wenn man ihn weglässt steht die Funktion aus dem Trait Bar einfach nicht zur Verfügung. === Veränderung der Sichtbarkeit von Methoden === <syntaxhighlight lang="php"> trait Foo { public function Bar { echo 'Hallo Welt!'; } } class Klasse1 { use Foo { Bar as private } } class Klasse2 { use Foo {Bar as private FooBar } } </syntaxhighlight> Hier verändern wir die Sichtbarkeit der Methode Bar in Klasse 1 und setzen die Sichtbarkeit für unsere Klasse 1 auf private. In Klasse 2 geben wir der Funktion die ebenfalls auf private gesetzt wird noch ein Alias namens "FooBar". == Traits und Vererbung == Traits können auch das "use" Konstrukt benutzen um einen anderen Trait zu implementieren: <syntaxhighlight lang="php"> trait Hallo { public function sagHallo { echo 'Hallo Welt!'; } } trait Mehr { public function sagMehr { echo ' Zweiter Trait'; } } trait HalloMehr { use Hallo, Mehr; } class Klasse1 { use HalloMehr; } $o = new Klasse1; $o->sagHallo; $o->sagMehr; </syntaxhighlight> Ausgabe: <pre> Hallo Welt! Zweiter Trait </pre> == Weitere Möglichkeiten in Traits == Es gibt noch einige weitere Möglichkeiten in Traits: Die Schlüsselwörter abstract und static werden unterstützt und funktionieren genauso wie in normalen Klassen, bis auf die Ausnahme, dass jede Klasse die einen statischen Member hat eine eigene Instanz hat davon. (Das heißt der statische Member ist an die Klasse die den Trait implementiert und nicht den Trait als solchen gebunden.) Außerdem ist es auch möglich Eigenschaften in Traits zu benutzen: <syntaxhighlight lang="php"> trait FooBar { public $foo = "Bar"; } </syntaxhighlight> Die Eigenschaften können dann von der Klasse die diesen Trait implementiert nicht mehr überschrieben werden. == PHP-Dokumentation == Folgender Abschnitt der PHP-Dokumentation wurde in diesem Kapitel behandelt: * [http://www.php.net/manual/de/language.oop5.traits.php Traits] <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Autoloading]] [[Websiteentwicklung: PHP: Autoloading|Zurück zu Autoloading]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Dependency Injection]] [[Websiteentwicklung: PHP: Dependency Injection|Vor zu Dependency Injection]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Dependency Injection= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Dependency Injection]] [[Websiteentwicklung: PHP: Dependency Injection|Dependency Injection]] </div> = Dependency Injection = Dependency Injection - zu deutsch etwa „Abhängigkeits-Injektion“ - beschreibt ein Verfahren, die von einer Klasse benötigten Objekte (Abhängigkeiten) von außen in die Klasse zu injizieren. Dies ist der Neigung vieler Anfänger entgegengesetzt, Objekte oftmals direkt in der Klasse zu instanziieren (erstellen). Beispiel direkter Instanzierung ('''keine''' Dependency Injection): <syntaxhighlight lang="php"> class MyController { private $logger; public function __contruct { $this->logger = new Logger; } public function myAction { $this->logger->log("someone called myAction"); } } </syntaxhighlight> Das Beispiel zeigt einen Controller ''MyController'', welcher über eine Methode ''myAction'' verfügt. Bei Aufruf dieser Methode soll ''someone called myAction'' geloggt werden. Der hierfür verantwortliche Logger mit der Klasse ''Logger'' wird im Konstruktor von ''MyController'' instanziiert. Somit hängt ''MyController'' von der Klasse ''Logger'' mit allen Ihren potentiellen Eigenheiten ab. Dies ist u. a. aus folgenden Gründen nicht erstrebenswert: * Verändert sich beispielsweise die Instanziierung der Klasse ''Logger'' (z. B. weil Argumente benötigt werden), muss die Klasse ''MyController'' ebenfalls angepasst werden * Verändern sich die Methoden der Klasse ''Logger'', müssen auch diese in ''MyController'' angepasst werden * Soll das ''Logger''-Objekt über Methoden konfiguriert werden, müsste auch dies direkt in ''MyController'' eingebaut werden Des Weiteren ist es strenggenommen nicht die Aufgabe von ''MyController'', sich um die Erstellung anderer Klassen zu kümmern (außer es würde sich um eine Klasse mit Factory-Methoden handeln). Es ist allgemein best practice, lediglich eine einzige Verantwortlichkeit (Responsibility) pro Klasse zu haben. Um nun den o. g. Missständen entgegenzuwirken, können wir Dependency Injection nutzen. Auch hier gibt es mehrere Arten, das Problem zu lösen - je nachdem, wie abhängig unsere Klasse wirklich von der zu injizierenden Abhängigkeit ist. == Möglichkeit 1: Constructor Injection == Anwendungsfall: Wenn jede Instanz der Klasse definitiv eine Instanz der Abhängigkeit benötigt oder die Abhängigkeit bereits im Konstruktor vorhanden sein muss (z. B. weil im Konstruktor Methoden aufgerufen werden, welche die Abhängigkeit benötigen). Beschreibung: Bei der Constructor Injection wird die Abhängigkeit als Konstruktorargument übergeben. Auf unser Beispiel bezogen hieße das, die ''MyController''-Klasse so umzubauen, dass unsere Abhängigkeit (die ''Logger''-Klasse) übergeben wird: <syntaxhighlight lang="php"> class MyController { private $logger; public function __construct(Logger $logger) { $this->logger = $logger; } public function myAction { $this->logger->log("someone called myAction"); } } </syntaxhighlight> An der Stelle, wo ''MyController'' instanziiert wird, muss nun eine Instanz der Klasse ''Logger'' übergeben werden: <syntaxhighlight lang="php"> $logger = new Logger; $myController = new MyController($logger); </syntaxhighlight> Das wirkt nun erstmal wenig speaktakulär. Vorteil ist hier jedoch, dass die Instanziierungslogik für die Klasse ''Logger'' nicht mehr in ''MyController'' benötigt wird. Wir haben ''MyController'' also bereits schlanker gemacht. Wollten wir nun z. B. den ''Logger'' noch konfigurieren, könnten wir das auch an dieser Stelle vornehmen: <syntaxhighlight lang="php"> $logger = new Logger; $logger->setTargetPath('/my/log.txt'); $logger->setLogLevel(2); $myController = new MyController($logger); </syntaxhighlight> Ansonsten hätten wir auch die Aufrufe der Methoden ''setTargetPath'' und ''setLogLevel'' in ''MyController'' platzieren müssen, was die Anfälligkeit dieser Klasse für Änderungen signifikant erhöht hätte. Hierzu ein weiteres Beispiel: Würde sich der Aufruf der Methode ''setLogLevel'' ändern und hätten wir diese in ''MyController'' aufgerufen, müssten wir nicht nur die ''Logger''-Klasse, sondern auch ''MyController'' anpassen. Hätten wir mehrere Controller-Klassen, in welchen wir genauso verfahren wären, müssten auch dort die Anpassungen vorgenommen werden. == Möglichkeit 2: Setter Injection == Anwendungsfall: Wenn die Abhängigkeit an bestimmten Stellen benötigt wird und vorher bekannt ist, ob das der Fall ist. Des Weiteren bei Abhängigkeiten, die austauschbar sein sollen oder in Fällen, wo Constructor Injection nicht genutzt werden kann/soll. Beschreibung: Bei dieser Form der Dependency Injection wird die Abhängigkeit über eine Setter-Methode hinzugefügt. <syntaxhighlight lang="php"> $logger = new Logger; $myController = new MyController; $myController->setLogger($logger); </syntaxhighlight> Die Klasse MyController sähe wie folgt aus: <syntaxhighlight lang="php"> class MyController { private $logger; public function setLogger(Logger $logger) { $this->logger = $logger; } public function myAction { $this->logger->log("someone called myAction"); } } </syntaxhighlight> Das ''Logger''-Objekt wird also einfach über die Methode ''setLogger'' gesetzt. Dies ist z. B. dann sinnvoll, wenn die Abhängigkeit ein großes Objekt ist und nur in ausgewählten, vorher bekannten Fällen benötigt wird. Wie weiter oben bereits beschrieben, muss darauf geachtet werden, dass die Abhängigkeit erst nach dem Aufruf der Setter-Methode (hier ''setLogger'') von der Klasse benötigt wird, da sie vorher in der Klasse nicht vorhanden ist. == Vor- und Nachteile == Der kritische Leser mag sich nun fragen, wo denn überhaupt der Vorteil der Dependency Injection liegt, haben wir doch lediglich die für das ''Logger''-Objekt notwendige Logik an eine andere Stelle verschoben. Auf unser einfaches Beispiel bezogen ist dieser Einwand durchaus berechtigt, denn etwaige Änderungen der ''Logger''-Klasse führen ggf. immer noch zu Änderungen an den Stellen, wo sie verwendet wird. Deshalb ist es notwendig, die Stelle der Instanziierung achtsam zu wählen. Beispielsweise könnte hierfür eine Stelle mit vielen verwandten Objektinstanziierungen oder gar eine Factory verwendet werden. Dennoch gibt es bereits jetzt Vorteile: * Die Klasse ''MyController'' muss nichts über die Instanziierung von ''Logger''-Objekten wissen * Wir könnten je nach Anwendungsfall Objekte der ''Logger''-Klasse unterschiedlich konfigurieren, bevor sie via Dependency Injection in ''MyController'' eingefügt werden * Hätten wir mehrere Controller-Objekte, könnten wir stets die gleiche ''Logger''-Instanz übergeben (bessere Performance) * Das Testen der ''MyController''-Klasse würde nun die Verwendung von speziellen Mock-Objekten für den ''Logger'' erlauben Es gibt allerdings immer noch einen gravierenden Nachteil: Die Klasse ''MyController'' ist von der Methode ''log'' der ''Logger''-Klasse abhängig. Änderungen an dieser Methode würden u. U. Änderungen an der ''MyController''-Klasse nach sich ziehen. Genau aus diesem Grund gibt es die sog. Interface Injection. == Möglichkeit 3: Interface Injection == Durch das bisherige Type Hinting im Konstruktor (Contructor Injection) bzw. der ''setLogger''-Methode (Setter Injection) in der ''MyController''-Klasse haben wir diese an die ''Logger''-Klasse gebunden. Sie muss nun zwar nicht mehr die Details der Instanziierung kennen, sich aber immer noch an den von der ''Logger''-Klasse zur Verfügung gestellten Methoden orientieren. Nun möchten wir diese Abhängigkeit auch noch auflösen. Anwendungsfall: Vermeidung der Abhängigkeit von konkreten Klassen (z. B. falls diese nicht bekannt sind und keine gemeinsame Parent-Klasse haben). Beschreibung: Wir könnten auch einfach das Type Hinting an entsprechenden Stellen komplett entfernen - dies hieße dann Duck Typing. So würde jedoch die Fehleranfälligkeit erhöht: Es könnte jedes Objekt übergeben werden und erst bei dem Aufruf einer Methode, die das übergebene Objekt nicht kennt, würde ein Fehler sichtbar werden (der dann noch zurückverfolgt werden müsste). Stattdessen sollten wir uns überlegen, was ''MyController'' eigentlich von ''Logger'' will. In unserem Fall wollen wir nur Loggen, mehr nicht. Und zwar über eine ''log''-Methode, die das, was wir loggen wollen, als Argument übergeben bekommt. Es ist unserer Klasse ''MyController'' völlig egal, ob der Logger, den sie nutzt, noch über Methoden wie ''setLogLevel'' oder ähnliche verfügt. Sie ist nur am einfachen Loggen über eine ''log''-Methode interessiert. Wir können also eine Schnittstelle (Interface) zwischen ''MyController'' und der ''Logger''-Klasse definieren: <syntaxhighlight lang="php"> interface LoggerInterface { public function log($message); } </syntaxhighlight> Dieses muss nun von der ''Logger''-Klasse [[Websiteentwicklung:_PHP:_Interfaces|implementiert werden]]. Nun können wir die Type Hints austauschen: ''Logger'' wird zu ''LoggerInterface'': <syntaxhighlight lang="php"> class MyController { private $logger; public function setLogger(LoggerInterface $logger) { $this->logger = $logger; } public function myAction { $this->logger->log("someone called myAction"); } } </syntaxhighlight> Diese Klasse hat nun keine Abhängigkeit mehr zur ''Logger''-Klasse. Jedes Objekt, dessen Klasse das ''LoggerInterface'' implementiert, kann hier übergeben werden. Würde die Klasse ''Logger'' nun die ''log''-Methode ändern, müsste sie sicherstellen, dass diese kompatibel zu dem von ihr implementierten Interface bleibt. Des Weiteren hätten wir die Möglichkeit, Objekte der ''MyController''-Klasse je nach Bedarf mit ganz unterschiedlichen Loggern auszustatten, die lediglich das ''LoggerInterface'' implementieren müssen. <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Traits]] [[Websiteentwicklung: PHP: Traits|Zurück zu Traits]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | </div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Muster Singleton= <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP Inhaltsverzeichnis]] | </div> =Singleton= Erzeugt genau eine Instanz eines Objektes. (vgl. [[Muster:_Singleton | WikiBook Muster]]) Es wird empfohlen sich das Benutzen eines Singletons genau zu überlegen, da es einige Nachteile mit sich bringen kann. Als Beispiel ist hier die feste Kopplung zu nennen, die ein Testen der Klasse aufwendiger macht. Sollte man dieselbe Instanz einer Klasse in mehreren anderen Klassen brauchen, empfiehlt es sich Dependency Injection zu benutzen, da durch diese Methode der Code um einiges flexibler wird als mit einem Singleton. ==Implementierung== <syntaxhighlight lang="php"> <?php class Singleton { /** * instance * * Statische Variable, um die aktuelle (einzige!) Instanz dieser Klasse zu halten * * @var Singleton */ protected static $_instance = null; /** * get instance * * Falls die einzige Instanz noch nicht existiert, erstelle sie * Gebe die einzige Instanz dann zurück * * @return Singleton */ public static function getInstance { if (null === self::$_instance) { self::$_instance = new self; } return self::$_instance; } /** * clone * * Kopieren der Instanz von aussen ebenfalls verbieten */ protected function __clone /** * constructor * * externe Instanzierung verbieten */ protected function __construct } ?> </syntaxhighlight> ==Beispiel== Das folgende Beispiel soll verdeutlichen, wie die oben beschriebene Implementierung verwendet wird. <syntaxhighlight lang="php"> <?php class Demo { /** * instance * * Statische Variable, um die aktuelle (einzige!) Instanz dieser Klasse zu halten * * @var Singleton */ protected static $_instance = null; public $value = 1; /** * get instance * * Falls die einzige Instanz noch nicht existiert, erstelle sie * Gebe die einzige Instanz dann zurück * * @return Singleton */ public static function getInstance { if (null === self::$_instance) { self::$_instance = new self; } return self::$_instance; } /** * clone * * Kopieren der Instanz von aussen ebenfalls verbieten */ protected function __clone /** * constructor * * externe Instanzierung verbieten */ protected function __construct } $demo1 = Demo::getInstance; $demo1->value = 5; echo '$demo1: $value = '.$demo1->value.'<br />'; $demo2 = Demo::getInstance; echo '$demo2: $value = '.$demo2->value; ?> </syntaxhighlight> <br /> '''Ausgabe''' $demo1: $value = 5 $demo2: $value = 5 == Weblinks == * [http://www.phphatesme.com/blog/softwaretechnik/das-singleton-richtig-implementiert/ Das Singleton, richtig implementiert] (deutsch) <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP Inhaltsverzeichnis]] | </div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Observer= ==Implementierung (ab Version 5)== <syntaxhighlight lang="php"> interface Subject{ public function register_observer(Observer $observer); public function remove_observer(Observer $observer); public function inform_observers; } class MySubject implements Subject{ private $observers = array; private $value; public function register_observer(Observer $observer){ $this->observers = $observer; } public function remove_observer(Observer $observer){ $offset = array_search($observer, $this->observers); unset($this->observers[$offset]); } public function inform_observers{ foreach($this->observers as $observer) { $observer->update($this->value); } } public function setValue($value){ $this->value = $value; $this->inform_observers; } } interface Observer{ public function update($value); } class MyObserver1 implements Observer { public function __construct(Subject $subject){ $subject->register_observer($this); } public function update($value){ print "I'm observer 1 and value is ".$value."\n"; } } class MyObserver2 implements Observer { public function __construct(Subject $subject){ $subject->register_observer($this); } public function update($value){ print "I'm observer 2 and value is ".$value."\n"; } } $mySubject = new MySubject; $myObserver1 = new MyObserver1($mySubject); $myObserver2 = new MyObserver2($mySubject); $mySubject->setValue(1); $mySubject->remove_observer($myObserver1); $mySubject->setValue(2); </syntaxhighlight> I'm observer 1 and value is 1 I'm observer 2 and value is 1 I'm observer 2 and value is 2 <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Dateisystem= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Dateisystem]] [[Websiteentwicklung: PHP: Dateisystem|Dateisystem]] </div> Die Funktionen des Dateisystems können genutzt werden um ASCII-Dateien auszulesen und zu schreiben. So können auch ohne Benutzung von MySQL z.B. Besucherzähler oder Gästebücher erstellt werden. ==Besucherzähler== Hier ein Beispiel für einen Besucherzähler mithilfe von Dateisystemfunktionen: <syntaxhighlight lang="php"> <?php $counter = file_get_contents("counter.txt"); $counter++; $f = fopen("counter.txt", "w"); fwrite($f,$counter,10); fclose($f); readfile("counter.txt"); ?> </syntaxhighlight> In der ersten Zeile wird mit der Funktion '''file_get_contents''' der Inhalt der Datei "counter.txt" in die Variable ''$counter'' eingelesen. Die Funktion '''fopen''' öffnet die Datei "counter.txt". Das "w" steht für write, die Datei wird also zum Schreiben geöffnet. '''fwrite''' schreibt den Inhalt der Variablen ''$counter'' in "counter.txt". Der Befehl '''fclose''' schließt die Datei wieder. Mit '''readfile''' wird der gesamte Inhalt der Datei ausgegeben inkl. der Größe der Datei in Bytes. <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Include]] [[Websiteentwicklung: PHP: Include|Zurück zu Quellcode wiederverwenden (Include)]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Mails]] [[Websiteentwicklung: PHP: Mails|Vor zu Mails]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Zugriff auf andere Webseiten= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Zugriff auf andere Webseiten]] [[Websiteentwicklung: PHP: Zugriff auf andere Webseiten|Zugriff auf andere Webseiten]] </div> Für den Zugriff auf andere Webseiten, muss "allow_url_fopen" in der php.ini aktiviert sein. Hier sehen Sie ein Beispiel für den Zugriff auf example.com und das systematische Durchsuchen der Seite nach h1-Tags. Mit diesem Beispiel kann man den Inhalt einer anderen Seite speichern: <syntaxhighlight lang="php"> <?php $datei = fopen ("http://www.example.com/", "r"); if (!$datei) { echo "Datei konnte nicht geöffnet werden."; exit; } while (!feof ($datei)) { $line = fgets ($datei, 1024); if (preg_match ("@\<h1\>(.*)\</h1\>@i", $line, $hits)) { $headline = $hits[1]; break; } } echo $headline; //=> "Example Domains" siehe example.com fclose($datei); ?> </syntaxhighlight> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Mails= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Mails]] [[Websiteentwicklung: PHP: Mails|Mails]] </div> PHP allein kann keine E-Mails verschicken, benötigt wird ein auf dem Webserver laufender Mailserver, der den Versand übernimmt. == Mails versenden mit der mail-Funktion == Die Mail-Funktion kann genutzt werden, um automatisch E-Mails zu verschicken. <syntaxhighlight lang="php"><?php mail('mustermann@beispiel.de', 'Betreff', 'Nachricht'); ?></syntaxhighlight> Hiermit wird eine E-Mail an mustermann@beispiel.de mit dem Betreff "Betreff" und der Nachricht "Nachricht" versandt. <syntaxhighlight lang="php"><?php mail( 'mustermann@beispiel.de', 'Betreff', 'Nachricht', 'From: ich@beispiel.de\r\nReply-To: ich@beispiel.de' ); ?></syntaxhighlight> Dies versendet die gleiche E-Mail wie im ersten Beispiel, allerdings werden auch die Befehle "From:" und "Reply-To" benutzt. Mit diesen Befehlen machst du es der angeschriebenen Person möglich, dir zu antworten. Außerdem erkennen manche Provider E-Mails ohne "From:" und "Reply-To" als Spam und sie werden automatisch gelöscht. == Mails versenden mit einem Mail-Framework == In der Praxis kann die Benutzung von mail sehr mühsam und fehleranfällig sein. Ohne vorherige Authentifizierung werden Mails zudem oft abgelehnt (dank unzähliger Spammer). Daher empfiehlt es sich, auf ein vorhandenes Mail-Framework zurückzugreifen. === Verwendung von PHPMailer === PHPMailer kann [https://github.com/PHPMailer/PHPMailer auf Github] heruntergeladen werden. Auf dieser Seite ist auch eine kurze Erklärung zur Verwendung von PHPMailer. Um PHPMailer verwenden zu können, müssen Sie die Dateien "class.phpmailer.php", "class.pop3.php" und "class.smtp.php" in einen Ordner Ihrer Wahl auf den Server legen. Hier ist nun ein kleines Beipiel wie PHPMailer verwendet werden kann: <syntaxhighlight lang="php"> <?php require 'pfadzurphpmailerklasse/class.phpmailer.php'; // Einfügen der PHPMailer-Klasse $mail = new PHPMailer; // PHPMailer Objekt erstellen $mail->IsSMTP; // Set mailer to use SMTP $mail->Host = 'smtp1.example.com;smtp2.example.com'; // Specify main and backup server $mail->SMTPAuth = true; // Enable SMTP authentication $mail->Username = 'jswan'; // SMTP Username $mail->Password = 'secret'; // SMTP Passwort $mail->SMTPSecure = 'tls'; // Enable encryption, 'ssl' also accepted $mail->From = 'from@example.com'; // Absendeadresse $mail->FromName = 'Mailer'; // Absendename $mail->AddAddress('josh@example.net', 'Josh Adams'); // Add a recipient $mail->AddAddress('ellen@example.com'); // Name is optional $mail->AddReplyTo('info@example.com', 'Information'); $mail->AddCC('cc@example.com'); $mail->AddBCC('bcc@example.com'); $mail->WordWrap = 50; // Setzt Zeilenumbruch auf 50 Zeichen $mail->AddAttachment('/var/tmp/file.tar.gz'); // Fügt Anhang hinzu $mail->AddAttachment('/tmp/image.jpg', 'new.jpg'); // Fügt Anhang mit optionalem Namen hinzu $mail->IsHTML(true); // Email wird im HTML-Format versendet $mail->Subject = 'Here is the subject'; $mail->Body = 'This is the HTML message body <b>in bold!</b>'; $mail->AltBody = 'This is the body in plain text for non-HTML mail clients'; if(!$mail->Send) { echo 'Message could not be sent.'; echo 'Mailer Error: ' . $mail->ErrorInfo; exit; } echo 'Nachricht wurde versendet!'; </syntaxhighlight> === Verwendung von Zend Mail === === Verwendung von Swiftmailer === === Verwendung von PEAR Mail === <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Dateisystem]] [[Websiteentwicklung: PHP: Dateisystem|Zurück zu Dateisystem]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Cookies]] [[Websiteentwicklung: PHP: Cookies|Vor zu Cookies]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Hashfunktionen= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Hashfunktionen]] [[Websiteentwicklung: PHP: Hashfunktionen|Hashfunktionen]] </div> == Was sind überhaupt Hashfunktionen? == == Hashfunktionen zur Verschlüsselung von Passwörtern == Die Passwörter einer Webanwendung mit Hilfe von Hashfunktionen zu verschlüsseln, ist eine der wichtigsten Sicherheitsvorkehrungen. Die Ideen dahinter ist es Passwörter bevor sie in einer Datenbank gespeichert werden, mit Hilfe einer Hashfunktion zu verschlüsseln. Wenn sich nun eine Person anmelden möchte, wird ihr Passwort auch verschlüsselt und mit dem verschlüsselten Passwort in der Datenbank verglichen. Sollten sie gleich sein hat der User das Passwort richtig eingegeben. Sollte nun eine Person die Userdatenbank in die Hände bekommen, kann sie die Passwörter nicht einfach entschlüsseln, da eine Hashverschlüsselung eine Ein-Weg-Verschlüsselung ist. Er müsste alle möglichen Passwörter verschlüsseln und mit dem verschlüsselten Passwort in der Datenbank vergleichen. === Angriffsarten === Die Brute-Force-Attacke ist die zeitaufwendigste Angriffsart. Es werden nacheinander alle möglichen Zeichenketten verschlüsselt und mit dem Hashcode verglichen. Eine Wörterbuchattake verwendet, wie der Name schon sagt ein Wörterbuch zum Knacken eines Hashcodes und funktioniert ähnlich wie die Brute-Force-Attake. Da Passwörter leider im Normalfall aus Wörtern bestehen, probiert bei einer Wörterbuchattake ein kleines Programm einfach verschiedene Wortkombinationen aus um den Hashcode zu erraten. Rainbowtables sind automatisch erstellte Tabellen, in welchen irgendwelche Wörter und deren Verschlüsselungen stehen. Diese Tabellen werden meist von sehr schnellen Rechnern erstellt und machen das entschlüsseln eines verschlüsselten Passworts um einiges einfacher. Es muss nur noch das verschlüsselte Passwort in der Tabelle gesucht werden und schon hat man das Passwort entschlüsselt. Um sich vor den oben genannten Angriffen zu schützen gibt es ein paar Punkte die beachtet werden sollten: # Zwingen sie ihre User dazu gute Passwörter zu verwenden. # Verwenden sie gute und sichere Verschlüsselungsalgorithmen. # Verwenden sie auf Salt und Pepper, welche im nächsten Abschnitt behandelt werden. === Salt und Pepper === Salting ist eine relativ simple Technik um sich vor den oben genannten Angriffsarten zu schützen. Die Idee hinter Salting ist es eine beliebige Zeichenkette (Salt) vor dem Verschlüsseln an das Passwort anzuhängen und auch in der Datenbank abzuspeichern. Nun sind Rainbowtables ziemlich wirkungslos, da es vielleicht einen Eintrag für das Passwort "hallo" gibt, aber es sehr unwahrscheinlich ist, dass es einen Eintrag für das Passwort ("hallo" + Salt) gibt, vor allem da Salts im Normalfall relativ lange und möglichst zufällige Zeichenketten sind. Ein Pepper ist eine weitere Sicherheitsvorkehrung, welche ähnlich funktioniert wie Salting. Es wird dabei vor dem Verschlüsseln nicht nur der Salt an das Passwort gehängt sondern auch der Pepper. Der Pepper ist eine Zeichenkette die zum Beispiel in einer PHP-Konstante gespeichert wird und für die ganze Webanwendung gleich ist. Sollte es also nun einer Person gelingen an die Userdatenbank zu gelangen, nützt im das relativ wenig, weil er auch den Pepper genötigt, welcher nicht in der Datenbank gespeichert ist. === Die Methoden md5, sha1 und sha256 === Die Methoden md5, sha1 und sha256 wurden früher sehr gerne für Passwortverschlüsselungen verwendet, jedoch sind die heutigen Computer so leistungsstark, dass es nicht mehr sehr sicher ist sie zu verwenden. Hier ist trotzdem ein kleines Beispiel: <syntaxhighlight lang="php"> $md5Hash = md5($password); $sha1Hash = sha1($password); $sha256Hash = sha256($password); </syntaxhighlight> === Die Methoden hash und crypt === === Hashing mit Frameworks === ==== PHPass ==== == Hashfunktionen zur Erstellung vom Prüfsummen == == Weblinks == * [http://php.net/manual/en/faq.passwords.php http://php.net/manual/en/faq.passwords.php] <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Reguläre Ausdrücke= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Reguläre Ausdrücke]] [[Websiteentwicklung: PHP: Reguläre Ausdrücke|Reguläre Ausdrücke]] </div> Mit regulären Ausdrücken werden explizite Eingaben von Benutzern in Formularen auf ihre Korrektheit überprüft. Damit wird überprüft, ob die eingegebene Zeichenkette dem definierten Muster entspricht. Es wird nun ersichtlich, dass einzugebenden Felder innerhalb eines Formulares mit diesen Mustern versehen werden können. Somit wird nicht nur gewährleistet, dass die gewollten Informationen erhalten werden, es entspricht auch dem Sicherheitsaspekt, sich vor diversen Attacken zu schützen. ==Einführung== Ein regulärer Ausdruck könnte z.B. so aussehen: /^f(o|a)o$/mi Die Schrägstriche ("/") agieren hierbei als ''Delimiter'', also als Begrenzer. Man könnte auch Ausrufezeichen o.ä. verwenden. Der gesamte RegEx besteht damit aus zwei Teilen: "^f(o|a)o$" und "mi". "mi" sind Modifikatoren, auf die später eingegangen wird. In dem ersten Teil des RegEx wird das allgemeine Schema das Suchmusters definiert, prinzipiell besteht es aus aufeinanderfolgenden Gruppierungen, ein String, der gefunden wird, muss daher folgende Kriterien erfüllen: Am Anfang einer Zeile (das Zeichen "^" mit dem Modifikator "m") muss ein "f" stehen, darauf folgt ein Teil, der auf (o|a) passt, darauf folgt ein o und darauf das Ende der Zeile ("$" mit Modifikator "m"). "(o|a)" ist hierbei ein Submuster, in diesem Fall ein simples, es muss entweder ein "o" oder ein "a" folgen. Da dies das erste Submuster im Suchmuster ist, wird der tatsächliche Inhalt (also entweder "o" oder "a") in der Variable ''\1'' abgelegt. Die Groß- und Kleinschreibung wird auf Grund des Modifikators "i" ('''''i'''gnore case'') ignoriert. Das Suchmuster passt daher auf z.B. folgende Zeilen: foo fao FaO fOO ==Zeichenklassen und klassenartige Konstrukte== {| |[...] || Irgendein Zeichen aus der Liste |- |[^...] || Irgendein Zeichen, das sich nicht in der Liste befindet |- |[:Klasse:] || Zeichenklasse im POSIX-Stil; nur innerhalb einer Regex Zeichenklasse gültig |- |. || Beliebiges Zeichen außer dem Newline-Zeichen, [^\n] |- |\C || Ein Byte; kann allerdings einen Unicode-Zeichenstream beschädigen |- |\w || Wortzeichen, [a-zA-Z0-9_] |- |\W || Nicht-Wortzeichen, [^a-zA-Z0-9_] |- |\d || Ziffer, [0-9] |- |\D || Nicht Ziffer, [^0-9] |- |\s || Whitespace-Zeichen, [\n\r\f\t ] |- |\S || Nicht Whitespace-Zeichen, [^\n\r\f\t ] |} ==Anker und Zusicherungen der Länge null== {| |^ || Anfang des Strings bzw. im Mehrzeichenmodus (/m) nach jedem Newline |- |\A || Anfang des Suchstrings in allen Match-Modi |- |$ || Ende des Strings oder vor einem den String abschließenden Newline |- |\G || Anfang der aktuellen Suche |- |\b || Wortgrenze |- |\B || Nicht-Wortgrenze |- |(?=...) || Positives Lookahead |- |(?!...) || Negatives Lookahead |- |(?<=...) || Positves Lookbehind |- |(?<!...) || Negatives Lookbehind |} ==Kommentare und Modus-Modifikationen== {| |i || Groß-/Kleinschreibung ignorierendes Matching |- |m || ^ und $ greifen auch neben eingebettetem \n |- |s || Punkt (.) erkennt Newline |- |x || Ignoriert Whitespace und erlaubt Kommentare (#) in Mustern. |- |U || Kehrt die >>Gier<< aller Quantoren um: * wird nicht-gierig und *? gierig. |- |A || Matching beginnt am Anfang der Suche |- |D || $ greift am Ende Strings und nicht vor dem newline, das den String abschließt. |- |u || Betrachtet regulären Ausdruck und Subject-Strings als Strings in Multibyle-UTF-8-Zeichen |- |(?#...) || Betrachet Substrings als Kommentar |- |#... || Betrachet den Rest der Zeile als Kommentar |} ==Gruppierung== {| |(...) || Gruppierung von Submustern |- |(?P<Name>) || Submuster gruppieren und Subtreffer in benannter Capture-Gruppe ''Name'' festhalten |- |\n || Enthält das Ergebnis des n-ten vorangegangen Subtreffers einer geklammerten oder benannten Capture-Gruppe |- |(?:...) || Submuster gruppieren, aber keine Subtreffer festhalten |- |(?>...) || Backtracking für durch Submuster erkannten text deaktivieren |- | ...|... || Submuster in Alternativen probieren |- |* || Keinmal oder mehrmals |- | + || Einmal oder mehrmals |- |? || Einmal oder keinmal |- |{n} || Genau n-mal |- |{n,} || Mindestens n-mal |- |{x,y} || Mindestens x-mal, aber nicht öfter als y-mal |- |*? || Keinmal oder mehrmals, aber so wenig wie möglich |- | +? || Einmal oder mehrmals, aber so wenig wie möglich |- |{n,}? || Mindestens n-mal, aber so wenig wie möglich |- |{x,y}? || Mindestens x-mal, nicht mehr als y-mal und so wenig wie möglich |- |*+ || Kein- oder mehrmals und kein Backtracking |- | ++ || Einmal oder mehrmals und kein Backtracking |- |?+ || Kein- oder einmal und kein Backtracking |- |{n}+ || Genau n-mal und kein Backtracking |- |{n,}+ || Mindestens n-mal und kein Backtracking |- |{x,y}+ || Mindestens x-mal, nicht mehr als y-mal und kein Backtracking |} ==Die PHP-Funktionen== ===preg_match=== <syntaxhighlight lang="php"> <?php $datum = '01-03-2004'; if (preg_match('/^(\d{2})-(\d{2})-(\d{4})$/', $datum, $wert)){ echo $wert[0]; } else { echo 'Ungültiges Datumsformat: '.$datum; } ?> </syntaxhighlight> Zuerst wird eine Variable '''$datum''' mit einem Datumsmuster versehen. Alle eingegebenen Datumsmuster '''müssen''' dem obigen Muster entsprechen, ansonsten wird die in else eingegebene Funktion ausgegeben. ===preg_replace=== <syntaxhighlight lang="php"> $string = '[[image:foo.jpg|Alternativtext]]'; $string = preg_replace('/\[\[image:(.+)\|(.+)\]\]/i', "<img src='$1' alt='$2'/>", $string); </syntaxhighlight> Ersetzt in einem String Wiki-formatierte Bilder nach HTML. == Weiterführende Links == * https://regex101.com/ - Reguläre Ausdrücke online testen <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Sessions]] [[Websiteentwicklung: PHP: Sessions|Zurück zu Sessions]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Rekursion]] [[Websiteentwicklung: PHP: Rekursion|Vor zu Rekursion]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Rekursion= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Rekursion]] [[Websiteentwicklung: PHP: Rekursion|Rekursion]] </div> ==Was ist Rekursion?== Rekursive Funktionen sind vereinfacht gesagt Funktionen, die in ihrer Ausführung sich selbst noch ein mal aufrufen mit einem veränderten Argument. ==Ein Beispiel== Hier ein kleines Beispiel zur [[w:Rekursion|Rekursion]] mit einer rekursiven PHP Funktion f zur Berechnung der [[w:Fakultät (Mathematik)|Fakultät]] einer ganzen Zahl: <syntaxhighlight lang="PHP" line start="1"> function f($i) { if (!is_integer($i) or $i < 1) { return "Fehler"; } if ($i == 1) { return $i; } else { /* return $i * f(--$i); kann nicht verwendet werden, da --$i zuerst dekrementiert!!! */ $temp = $i; return $temp * f(--$i); } } </syntaxhighlight> In Zeile 3 prüft die Funktion, ob der Aufrufparameter gültig ist und beendet sich, falls der Parameter keine ganze Zahl (<code>is_integer</code>) oder kleiner 1 ist. Die Zeile 8 enthält die Abbruchbedingung für die Rekursion: Sobald der Parameter 1 ist, liefert die Funktion 1 zurück (und ruft sich nicht mehr selbst rekursiv auf). Wird die Abbruchbedingung nicht erfüllt, erfolgt in Zeile 14 die eigentliche Rekursion durch Aufruf von f(<code>--$i</code>). Hier wird der Parameter <code>$i</code> zuerst dekrementiert, bevor er der Funktion übergeben wird. Das führt dazu, dass die Variable <code>$i</code> in der Zeile VOR Auswertung dekrementiert wird (an BEIDEN Stellen) - deshalb ist eine Zwischenvariable nötig. So wird - hoffentlich - sichergestellt, dass die Funktion einmal abbricht, wenn der Parameter < 2 wird. Aufruf erfolgt dann z.B.: <syntaxhighlight lang="PHP" line start="1"> $f = f(5); </syntaxhighlight> Dieses einfache Beispiel kann auch als while-Konstrukt ohne Rekursion realisiert werden: <syntaxhighlight lang="PHP" line start="1"> function f($i) { if (!is_integer($i) or $i < 1) { return "Fehler"; } $ret = $i; while ($i-- > 1) { $ret *= $i; } return $ret; } </syntaxhighlight> <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Reguläre Ausdrücke]] [[Websiteentwicklung: PHP: Reguläre Ausdrücke|Zurück zu Reguläre Ausdrücke]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: PHP-Referenz]] [[Websiteentwicklung: PHP: PHP-Referenz|Vor zu PHP-Referenz]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Gzip-Komprimierung= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Gzip-Komprimierung]] [[Websiteentwicklung: PHP: Gzip-Komprimierung|Gzip-Komprimierung]] </div> ==Wozu das Ganze?== Um Webseiten schneller laden zu lassen gibt es verschiedene Möglichkeiten. Eine davon ist die Komprimierung mittels Gzip. Dieses Verfahren beherrschen alle gängigen Browser ohne Probleme. Dabei wird die gesamte Seite bevor sie zum Benutzer geschickt wird auf dem Server komprimiert und dann im komprimierten Zustand an den Benutzer gesendet. Dabei kann die Datenmenge die gesendet werden muss um einiges verringert werden. Google empfiehlt in seinen Regeln für schnelle Webseiten, dass man seine Seite per Gzip komprimiert senden sollte. Doch so wie jedes andere auch, hat auch dieses Verfahren seine Nachteile. Durch die Komprimierung auf dem Server und das Entpacken beim Benutzer wird bei beiden mehr CPU beansprucht. Die Gzip Komprimierung kann entweder über die Konfigurationsdateien ihres Web-Servers (z.b. Apache) oder über eine Funktion in PHP aktiviert werden. Falls sie keinen Zugriff haben auf die Konfigurationsdateien (z.b. bei Webhosting Lösungen) bleibt nur die Möglichkeit über PHP. ==Komprimierung in PHP== Wie aktiviert man die Komprimierung mittels PHP? <syntaxhighlight lang="php"> <?php if(!ob_start("ob_gzhandler")) ob_start; //hier der GANZE Code ob_end_flush; ?> </syntaxhighlight> Wichtig hierbei ist, dass der Befehl "ob_start" in der 1. Zeile ausgeführt wird. Dadurch wird wirklich alles per Gzip komprimiert an den Benutzer geschickt. Sollte der Benutzer kein Gzip unterstützen (bei sehr alten Browsern der Fall) wird automatisch die normale "Output Buffering" Methode angewandt, bei der die ganze Ausgabe am Ende gesammelt (unkomprimiert) gesendet wird. <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = JSON= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: JSON]] [[Websiteentwicklung: PHP: JSON|JSON]] </div> == JSON unter PHP == [http://www.json.org JSON] ist ein Standardformat zur Objektserialisierung. Es dient dazu, Objekte mit möglichst wenig Aufwand von einem System an ein anderes zu übertragen, und ist neben XML eines der derzeit beliebtesten Serialisierungsformate. Es findet oftmals Einsatz als Schnittstellenformat in HTTP-basierenden APIs und ist deswegen für PHP-Programmierer, die solche Dienste in ihre eigenen Webangebote integrieren möchten, von hoher Relevanz. == PHP-Objekte in JSON umwandeln == Um ein PHP-Objekt in einen JSON-Objektstring umzuwandeln unterstuetzt PHP die Methode <code>json_encode</code>. Was hierbei geschieht betrachten wir an einem kleinen Beispiel. Nehmen wir an, wir haben eine Klasse in PHP, die Personen abbildet, und erstellen wir ein konkretes Person-Objekt: <syntaxhighlight lang="php"> class Person { public $firstname = "wiki"; //Vorname public $lastname = "books"; //Nachname public $age = 20; //Alter public $pet = true; //Hat Haustier? } $testperson1 = new Person("wiki","books",21,true); // Erstelle eine Person, die Wiki Books heisst, 21 Jahre alt ist und ein Haustier hat. </syntaxhighlight> dann koennten wir das PHP-Objekt <code>$testperson1</code> folgendermassen in einen JSON-Objektstring umwandeln: <syntaxhighlight lang="php"> $testperson1_json = json_encode(get_object_vars($testperson1)); // Wandle $testperson1 in JSON um und speichere Ergebnis in $testperson1_json </syntaxhighlight> <code>$testperson1_json</code> haette nun folgenden Inhalt: <syntaxhighlight lang="javascript"> {"firstname":"wiki","lastname":"books","age":21,"pet":true} </syntaxhighlight> Wie wir sehen, wurden alle Attribute des Objekts <code>$testperson1</code> in die JSON-Repraesentation uebernommen, allerdings erst, nachdem wir uns mittels <code>get_object_vars</code> die Attribute des Objekts in einem assoziativen Array gespeichert haben. Wichtig ist: json_encode kann bis auf Objekte alle PHP bekannten Datenstrukturen (Array und assoziatives Array) in JSON-Objektstrings umwandeln. Das funktoniert auch, wenn die Datenstrukturen verschachtelt sind. == JSON in PHP-Objekte umwandeln == Um einen JSON-String in ein PHP-Objekt umzuwandeln stellt PHP die Funktion <code>json_decode</code> zur Verfuegung. Ihr Einsatz sieht aus wie folgt: <syntaxhighlight lang="php"> $json = '{"testattribut1":"hello world","testattribut2":1337,"testattribut3":true}'; $object = json_decode($json); </syntaxhighlight> <code>$object</code> Enthaelt nun ein generisches PHP-Objekt mit drei Attributen <code>$object->testattribut1</code>, <code>$object->testattribut2</code> und <code>$object->testattribut3</code>, die jeweils einen string, einen integer und einen booleschen Wert enthalten. Es kann in manchen Situationen sinnvoll sein, einen JSON-String nicht in ein Objekt umwandeln zu lassen, sondern in ein assoziatives Array. Das geht folgendermaßen: <syntaxhighlight lang="php"> $json = '{"testattribut1":"hello world","testattribut2":1337,"testattribut3":true}'; $array = json_decode($json,true); </syntaxhighlight> <code>$array</code> enthaelt jetzt ein assoziatives Array mit drei Key-Value-Paaren: <code>$array['testattribut1']</code>, <code>$array['testattribut2']</code> und <code>$array['testattribut3']</code>. <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: LDAP]] [[Websiteentwicklung: PHP: LDAP|Zurück zu LDAP]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Reguläre Ausdrücke]] [[Websiteentwicklung: PHP: Reguläre Ausdrücke|Vor zu Reguläre Ausdrücke]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = LDAP= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: LDAP]] [[Websiteentwicklung: PHP: LDAP|LDAP]] </div> == Kurze Einführung in LDAP == <div class="noprint kasten-interwiki" style="clear: right; border: solid #aaa 1px; margin: 0 0 1em 1em; font-size: 90%; background: #f9f9f9; width: 250px; padding: 3px; text-align: left; float: right;"> <div style="float: left;">[[Datei:Wikipedia-logo-v2-de.svg|50px|none|alt=]]</div> <div style="margin-left: 55px;">[[w:Wikipedia:Hauptseite|Wikipedia]] hat einen Artikel zum Thema:</div> <div style="margin-left: 65px;">'''''[[w: Lightweight Directory Access Protocol| Lightweight Directory Access Protocol]]'''''</div></div> '''LDAP''' ist eine Abkürzung für ''Lightweight Directory Access Protocol'', was soviel heißt wie "Leichtgewichtiges Verzeichnis-Zugriffs-Protokoll". Also ist ''LDAP'' das, im Gegensatz zu ''DAP'', weniger komplexe Protokoll, um auf ein "Verzeichnis" zuzugreifen, Ein Verzeichnisdienst ähnelt in seiner Funktionsweise zwar einer Datenbank, unterscheidet sich aber von traditionellen relationalen Datenbanken in folgenden Punkten: * Ein Directory ist mehr auf das Finden und Auslesen von Informationen spezialisiert als auf das Schreiben immer neuer Informationen. === Suchfilter === Eine LDAP-DB arbeitet nicht wie eine relationale Datenbank anhand von SQL-Statements, sondern anhand von Suchfilter. Das Format ist allgemein im [http://www.faqs.org/rfcs/rfc1960.html RFC 1960] definiert. Hier führen wir dich aber kurz in die wichtigsten Ausdrücke ein. Hier die Grundsätzlichen Filter: {|cellpadding="4" cellspacing="0" style="margin: 1em 1em 1em 0; background: #f9f9f9; border: 2px #000 solid; width=100%" rules="all" !Exakter Wert !Format !Beispiel !Resultate |- |Exakter Wert ||(&lt;attr&gt;=&lt;wert&gt;) ||(sn=Muster) ||Alle Personen mit dem Nachnamen ''Muster'' |- |ungefährer Wert ||(&lt;attr&gt;~=&lt;wert&gt;) ||(givenname~=Pascal) ||Alle Personen mit einem Vornamen,<br />welcher einen ähnlichen Ton hat wie ''Pascal''<br />('''Achtung''': Dies ist Server abhängig) |- |Teilzeichenkette ||(&lt;attr&gt;=[&lt;begin&gt;]*[&lt;text&gt;]*[&lt;ende&gt;]) ||(sn=*ust*) ||Alle Personen, welche im Nachnamen die Sequenz ''ust'' enthält. |- |Grösser gleich ||(&lt;attr&gt;&gt;=&lt;wert&gt;) ||(sn&gt;=Muster) ||Alle Nachnamen, welche im Lexikon an derselben Stelle wie ''Muster'' und nach ''Muster'' auftritt. |- |Kleiner gleich ||(&lt;attr&gt;&lt;=&lt;wert&gt;) ||(sn&lt;=Muster) ||Alle Nachnamen, welche im Lexikon an derselben Stelle wie ''Muster'' und vor ''Muster'' auftritt. |- |Vorhanden ||(&lt;attr&gt;=*) ||(sn=*) ||Alle Einträge mit Nachnamen. |} Die Basic-Filter können in jeder beliebigen Form kombiniert werden, wie man in der folgenden Tabelle sehen kann: {|cellpadding="4" cellspacing="0" style="margin: 1em 1em 1em 0; background: #f9f9f9; border: 2px #000 solid; width=100%" rules="all" !Exakter Wert !Format !Beispiel !Resultate |- |UND ||(&amp;(&lt;filter1&gt;)(&lt;filter2&gt;)...) ||(&amp;(givenname=Hans)(sn=Muster)) ||Einträge mit dem Vornamen ''Hans'' UND dem Nachnamen ''Muster'' |- |ODER ||(|(&lt;filter1&gt;)(&lt;filter2&gt;)...) ||(|(givenname=Hans)(sn=Muster)) ||Einträge mit dem Vornamen ''Hans'' ODER dem Nachnamen ''Muster'' |- |NICHT ||(!(&lt;filter1&gt;)) ||(!(mail=*)) ||Einträge ohne ein Mail-Attribut |} So nun kennst du alle Grundlagen, um deine eigenen Suchfilter zu schreiben. Bedenke aber, dass du nur Attribute, welche der Server kennt, nutzt, denn ansonsten kann dieses die Suche erheblich verlangsamen. === OpenLDAP installieren === ==== Linux ==== Um OpenLDAP auf einem Linux Computer zu installieren siehe [[Linux-Praxisbuch: Lightweight Directory Access Protocol#Installation des OpenLDAP|Linux-Praxisbuch: Lightweight Directory Access Protocol]] ==== Win32 ==== Siehe http://lucas.bergmans.us/hacks/openldap/ == LDAP mit PHP == Es gibt eine Vielzahl an Funktion, um auf einer LDAP-Datenbank zu kommunizieren. Hier werden nur die meist gebräuchlichsten erklärt: *<code><nowiki>ldap_connect ([string hostname[, int port]])</nowiki></code> - Stellt die Verbindung zu einem LDAP-DB-Server her. *<code><nowiki>ldap_bind(resource link_identifier[, string bind_rdn[, string bind_password]])</nowiki></code> - Logged sich beim Server ein, wobei die eigentlichen Userdaten optional sind. Standardmäßig wird man als anonymous eingelogged. *<code><nowiki>ldap_search(resource link_identifier, string base_dn, string filter[, array attributes[, int attrsonly[, int sizelimit[, int timelimit[, int deref]]]]])</nowiki></code> - Startet eine Suche in dem vorgegebenen Namespace und mit dem angegebenen [[#Suchfilter|Suchfilter]]. *<code><nowiki>ldap_get_entries(resource link_identifier, resource result_identifier)</nowiki></code> - Wandelt die Suchresultate in ein [[Websiteentwicklung: PHP: Arrays|Array]] um. *<code><nowiki>ldap_error(resource link_identifier)</nowiki></code> - Holt eine Fehlerbeschreibung des zuletzt aufgetretenen Fehlers. *<code><nowiki>ldap_delete(resource link_identifier, string dn)</nowiki></code> - Löscht einen Eintrag des Verzeichnisses. *<code><nowiki>ldap_rename(resource link_identifier, string dn, string newrdn, string newparent, bool deleteoldrdn)</nowiki></code> - Ändert den Namen eines Eintrags. *<code><nowiki>ldap_add(resource link_identifier, string dn, array entry)</nowiki></code> - Fügt einen Eintrag hinzu. *<code><nowiki>ldap_modify(resource link_identifier, string dn, array entry)</nowiki></code> - Ändert Werte eines Eintrags. *<code><nowiki>ldap_unbind(resource link_identifier)</nowiki></code> '''oder''' <code><nowiki>ldap_close(resource link_identifier)</nowiki></code> - Schließt die Verbindung mit dem LDAP-Server. === Directory Zugriffe === '''Verzeichnislein, Verzeichnislein an der Wand wo wohnt ''cn=Hans Muster;ou=contacts,o=master,c=ch'' im kleinen Land?!?''' Nun diese Frage kann ein kleiner LDAP-Zugriff beantworten und dies sogar sehr schnell, auch wenn es mehrere 10000 Einträge gibt. ==== Mit Server Verbinden ==== Aber zuerst müssen wir auf das Directory verbinden (und falls nötig uns authentisieren, damit wir lesen können): <source lang="php"> // // Notiz: Für Windows 2003 AD kann es erforderlich sein, den Port (2. Argument) // für ldap_connect( $ldaphost, 3268 ) vom Standardwert (nichts angegeben) // auf 3268 zu ändern. (knito) // //''ldap.master.org'' ist der DNS-Name des LDAP-Servers $ldaphost = 'ldap.master.org'; $ldapconn = ldap_connect($ldaphost) or die("Could not connect to $ldaphost"); //''username'' und ''passwort'' sind optional, default ist anonymous-login if (ldap_bind($ldapconn, "username", "passwort")) { echo "Die Verbindung zu $ldaphost war erfolgreich"; } </source> <small>Der Verbindungsaufbau wird in den weiteren Beispielen nicht weiter beschrieben, um Platz zu sparen,</small> ==== Suchen ==== Nun, da wir mit dem Server verbunden sind, können wir dem Server unsere Frage stellen: <source lang="php"> /* * ''$ldapconn'' ist die Verbindung zum LDAP-Server vom ersten Beispiel */ $results = ldap_search($ldapconn, "ou=contacts,o=master,c=ch", "cn=Hans Muster"); /* Wie der Filter (letztes Argument) aufgebaut ist, siehe [[#Suchfilter|hier]] * * Die optionalen Argumente sind: * ''attributes'' - Nur diese Attribute sollen zurückgegeben werden, z.B. ''array("cn", "givenname", "sn") * ''attrsonly'' - ''1'' für nur die Attributtypen, ''0'' (default) * ''sizelimit'' - Die maximale Anzahl an Einträgen, welche zurückgegeben werden sollen. * ''timelimit'' - Die maximale Zeit, welche für die Suche genutzt werden darf. * ''deref'' - Bestimmt, wie Aliase behandelt werden sollen, bei dieser Suche. * -LDAP_DEREF_NEVER - (default) Aliase werden nie aufgelöst. Mögliche Werte: * -LDAP_DEREF_SEARCHING - Aliase sollen während der Suche aufgelöst werden, aber nicht dann, wenn das Basisobjekt der Suche ermittelt wird. * -LDAP_DEREF_FINDING - Aliase sollen aufgelöst werden, wenn das Basisobjekt ermittelt wird, aber nicht während der Suche. * -LDAP_DEREF_ALWAYS - Aliase sollen immer aufgelöst werden. */ // und nun die gefundenen Einträge verarbeiten $entries = ldap_get_entries($ldapconn, $results); echo "Es wurden ".$entries["count"]." Einträge gefunden"; if ($results != false) { foreach($entries as $entry) { //Gibt den eindeutigen Bezeichner (CommonName) des Eintrags aus. echo $entry["cn"][0]." (".$entry["cn"]["count"].")&lt;br&gt;\n"; } } </source> ==== Neuer Eintrag ==== Du hast einen hübschen Typen/eine schöne Frau kennengelernt und möchtest diese Person (Axel Muster) nun auch in deiner Datenbank speichern. Nach dem [[#Mit Server Verbinden|Verbinden]] zur Datenbank aufgebaut hast, muss nur eine einzelne Methode aufgerufen werden: <source lang="php"> ldap_add($ldapconn, "cn=Axel Muster,ou=contacts,o=master,c=ch", array( "cn" => array("Axel Muster"), //CommonName "givenname" => array("Axel"), //Vorname "sn" => array("Muster"), //Nachname (SurName) "objectclass" => array("pabPerson", "inetOrgPerson", "organizationalPerson", "person", "top"), //Eintrag typen "telephonenumber" => array("784'351'92'34"), //Telefonnummer "mobile" => array)); //Handy-Nummer </source> ==== Umbenennen ==== Eine gute Kollegin (Nadine Schindel) hat nun geheiratet und übernimmt den Namen ihres Ehemanns (Fabian Wickihalder), nun möchtest du diesen Eintrag auch in deiner Datenbank aktualisieren: <source lang="php"> ldap_rename($ldapconn, "cn=Nadine Schindel,ou=contacts,o=master,c=ch", //Der alte Eintrag, welcher gemoved/umbenannt werden soll. "cn=Nadine Wickihalder,ou=contacts,o=master,c=ch", //Der neue Name des alten Eintrags. "ou=contacts,o=master,c=ch", //Da wir diesen Eintrag nicht in einen anderen Namespace verschieben, bleibt dies gleich. true); //Der alte Eintrag soll gelöscht werden (false, wäre beibehalten). </source> ==== Aktualisieren ==== Jemand (Hans Muster) hat seine Natel-Nummer geändert und nun werden wir diese kleine Information nachtragen <source lang="php"> ldap_modify($ldapconn, "cn=Hans Muster;ou=contacts,o=master,c=ch", array("mobile" => array("435'245'45'56"))) </source> ==== Löschen ==== Ein schlimmer Streit ist zwischen dir und einem Kollegen vorgekommen und du willst nichts mehr von dieser Person wissen, also löscht du seinen Eintrag (cn=Hans Muster;ou=contacts,o=master,c=ch) <source lang="php"> ldap_delete($ldapconn, "cn=Hans Muster;ou=contacts,o=master,c=ch") </source> == Specials == === phpLDAPAdmin === phpLDAPAdmin ist das LDAP-Equivalent zu phpMyAdmin, welches aber für MySQL-Datenbanken geschrieben wurde. Die Benutzeroberfläche ist gut organisiert, so dass keine weitere Ausführung nötig ist. ''' Installation ''' # Die php-sources von sourceforge herunterladen (http://phpldapadmin.sourceforge.net/download.php) # ''.tar.gz'' bzw. ''.zip'' File entpacken # Das Entpackte in einen Ordner verschieben, welcher durch den Webserver zugreifbar ist (Oft ''htdocs'' oder bei MacOSX Sites) # LDAP-Server-Zugriff konfigurieren # FERTIG ''' Konfiguration ''' Hier eine kleine Hilfestellung, wie man das LDAP-Tool phpLDAPAdmin konfiguriert. <font style="color:#FF0000;">TODO: Konfiguration beschreiben</font> === Bilder in der LDAP-DB === In diesem kleinen Spezial behandeln wir, welche Bedingungen erfüllt werden müssen, um ein Bild in der Datenbank speichern zu können und wie man solch ein Bild wieder ausliest. Da du denkst eine LDAP-DB ist genau das was du brauchst, um die Mitglieder deines Vereins zu verwalten, hast du eine Directory erstellt. Hier hast du die Möglichkeit, um die Daten in deiner Datenbank noch zu erweitern: Speichere ein Bild, z.B. von den wichtigsten Personen deines Vereins, in die DB. Dies ist ganz einfach: ''' Die Bedingungen ''' Die Attribute, in welchen man ein Bild speichern könnte, muss mit der ldapSyntax ''Binary'' (1.3.6.1.4.1.1466.115.121.1.5) bezeichnet sein. Das einfachste ist aber, wenn man das Attribut ''jpegPhoto'' von einen der Objekt-Klassen ''document'', ''inetOrgPerson'', ''pabPerson'', ''pilotObject'' benutzt. ''' Bild speichern ''' <source lang="php"> /* * ''$dn'' repräsentiert die DN worin das Bild gespeichert werden kann. * ''$data'' repräsentieren die JPG-Daten, welche z.B. mit ''fread'' aus einem File gelesen wurden. */ $ldapconn = $ldap_connect("ldap.master.org"); if ($ldapconn && $ldap_bind($ldapconn, "username", "passwort")) { //username und passwort sind optional $res = ldap_modify($ldapconn, $dn, array("jpegPhoto" => $data)); if (!$res) { echo "Fehler beim speichern des Bildes: ".ldap_error; } else { echo "Bild erfolgreich in $dn gespeichert."; } } ''' Bild auslesen ''' /* * Zur DB Verbinden... * ''$dn'' repräsentiert die DN des Eintrags */ $ldapconn = ldap_connect("ldap.master.org"); if ($ldapconn && ldap_bind($ldapconn, "username", "password")) { //username und password sind optional $search_result = ldap_read($ldapconn, $dn, 'objectClass=*'); $entry = ldap_first_entry($ldapconn, $search_result); $entry = ldap_get_values_len($ldapconn, $entry, "jpegPhoto"); $jpeg_data = $entry[0]; } </source> <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Cookies]] [[Websiteentwicklung: PHP: Cookies|Zurück zu Cookies]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Dateisystem]] [[Websiteentwicklung: PHP: Dateisystem|Vor zu Dateisystem]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = PHP-Referenz= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: PHP-Referenz]] [[Websiteentwicklung: PHP: PHP-Referenz|PHP-Referenz]] </div> == Kontrollstrukturen == {| class="wikitable" |- ! Befehl !! Beschreibung !! Link |- | if || || [[Websiteentwicklung: PHP: Kontrollstrukturen|Kontrollstrukturen]] |- | switch || || [[Websiteentwicklung: PHP: Switch-Abfrage|Switch-Abfrage]] |- | while || Schleife || [[Websiteentwicklung: PHP: Schleifen|Schleifen]] |- | do {...} while || Schleife || [[Websiteentwicklung: PHP: Schleifen|Schleifen]] |- | for || Schleife || [[Websiteentwicklung: PHP: Schleifen|Schleifen]] |- | foreach || Schleife || [[Websiteentwicklung: PHP: Schleifen|Schleifen]] |} == Stringfunktionen == {| class="wikitable" |- ! Funktionsname !! Beschreibung !! Link zur PHP-Referenz |- | trim || Entfernt Whitespace am Anfang und am Ende eines Strings || [http://www.php.net/manual/de/function.trim.php Link] |- | ltrim || Entfernt Whitespace oder andere Zeichen vom Anfang eines Strings || [http://www.php.net/manual/de/function.ltrim.php Link] |- | rtrim || Entfernt Whitespace oder andere Zeichen vom Ende eines Strings || [http://www.php.net/manual/de/function.rtrim.php Link] |- | str_replace || Zeichenkette ersetzen || [http://www.php.net/manual/de/function.str-replace.php Link] |- | strtolower || Ersetzt alle Großbuchstaben eines Strings durch Kleinbuchstaben || [http://www.php.net/manual/de/function.strtolower.php Link] |- | strtoupper || Ersetzt alle Kleinbuchstaben eines Strings durch Großbuchstaben || [http://www.php.net/manual/de/function.strtoupper.php Link] |} == Weblinks == * Alle PHP-Funktionen: http://php.net/quickref.php <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Rekursion]] [[Websiteentwicklung: PHP: Rekursion|Zurück zu Rekursion]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Übungsbeispiele]] [[Websiteentwicklung: PHP: Übungsbeispiele|Vor zu Übungsbeispiele]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Fehlerquellen= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Fehlerquellen]] [[Websiteentwicklung: PHP: Fehlerquellen|Fehlerquellen]] </div> Gerade bei Anfängern kommt es oft vor, dass ein Programm nicht das tut, was der Programmierer erwarten würde. Grundsätzlich können wir drei Arten von Fehlern unterscheiden: #logische Fehler #Syntaxfehler #PHP-Fehler == Syntaxfehler == Wie in den vorangegangenen Kapiteln erklärt, erwartet der PHP-Parser eine gewisse Syntax für den Code. Kommt ihm dabei ein Zeichen in die Quere, welches er nicht erwartet, wird das Programm nicht ausgeführt sondern eine Fehlermeldung ausgegeben. Ist die Ausgabe von Fehlermeldungen ausgeschaltet, erscheint sogar nur eine leere Seite. In diesem Fall sollte im ersten Schritt die Ausgabe von Fehlermeldungen eingeschaltet werden. Beliebte Fehler sind: # das Vergessen eines ; oder einer } (in diesem Fall gibt die Zeilennummer in der Fehlermeldung oft den ungefähren Ort an) # eine Datei die vom Skript eingebunden wird, wird nicht gefunden (oft eine Folge falscher Pfadangaben) == Logikfehler == Diese Art von Fehlern ist schwerer zu finden und zu beheben. Logische Fehler liegen nämlich vor, wenn das Programm vollständig läuft, die Ausgabe(n) oder das Verhalten allerdings nicht den Erwartungen des Programmierers entsprechen. == PHP-Fehler == Da es sich auch bei PHP selbst um ein Programm handelt, können auch bei PHP-Befehlen selbst Fehler auftreten. Als Anfänger beim Programmieren sollte man allerdings den Fehler zuerst bei seinem Code selbst suchen, und nicht bei PHP. <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Übungsbeispiele]] [[Websiteentwicklung: PHP: Übungsbeispiele|Zurück zu Übungsbeispiele]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung:_PHP]] [[Websiteentwicklung:_PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung:_PHP:_Templates]] [[Websiteentwicklung:_PHP:_Templates|Vor zu Template Engines]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = PEAR= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: PEAR]] [[Websiteentwicklung: PHP: PEAR|PEAR]] </div> PEAR (Abkürzung für „PHP Extension and Application Repository“) ist eine Sammlung (Bibliothek) von Modulen und Erweiterungen für die Skriptsprache PHP, ähnlich dem Projekt CPAN für Perl. Die Programmmodule und Erweiterungen verkürzen den Entwicklungsprozess von PHP-Anwendungen erheblich, da sie dem Programmierer viele Standard-Aufgaben abnehmen. Hierdurch wird auch ein höheres Maß an Sicherheit bei der Anwendungsentwicklung erzeugt, da der Entwickler auf qualitätsgesicherte Standardkomponenten zurückgreift. ==Installation== unter Unix: <syntaxhighlight lang="php"> //Liste aller Verfügbaren Pakete (engl.: packages) pear list-all //Liste aller Verfügbaren Upgrades pear list-upgrades //Liste aller installierten Pakete pear list //Installiere Paket pear install Paketname </syntaxhighlight> ==Auflistung von einigen Pakete== * Authentication * Caching * Console * Date and Time * Event * File System * HTML * Images * Logging * Math * PEAR * Processing * Semantic Web * Structures * Text * Validate * XML * Benchmarking * Configuration * Database * Encryption * File Formats * Gtk Components * Internationalization * Mail * Networking * Payment * Science * Streams * System * Tools and Utilities * Web Services == Beispiel: das Paket HTML == Diese Gruppe besteht derzeit aus 27 Paketen, die meisten davon dienen der Layoutunterstützung. * HTML_AJAX * HTML_BBCodeParser * HTML_Common * HTML_Common2 * HTML_Crypt * HTML_CSS * HTML_Form * HTML_Javascript * HTML_Menu * HTML_Page * HTML_Page2 * HTML_Progress * HTML_QuickForm * HTML_QuickForm_Controller * HTML_QuickForm_SelectFilter * HTML_Select * HTML_Select_Common * HTML_Table * HTML_Table_Matrix * HTML_Template_Flexy * HTML_Template_IT * HTML_Template_PHPLIB * HTML_Template_Sigma * HTML_TreeMenu * Pager * Pager_Sliding === Beispiele aus dem Paket HTML === * [[Websiteentwicklung: PHP: PEAR: HTML QuickForm|QuickForm]] * [[Websiteentwicklung: PHP: PEAR: Pager|Pager]] <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Firebird= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Firebird]] [[Websiteentwicklung: PHP: Firebird|Firebird]] </div> == Firebird unter PHP == Firebird ist ein quelloffenes, relationales Datenbanksystem, das als Fork aus <i>Borland</i>s Datenbanksystem <i>Interbase</i> hervorging. Es beherrscht ACID-kompatible Transaktionen, BLOBs, Sequenzen, Trigger und kann ohne ODBC oder sonstige Zwischenschichten von PHP angesprochen werden. Somit ist es wie geschaffen fuer ein breites Feld an Einsatzzwecken. Hinweis: Dieser Artikel bezieht sich auf einen in einer Linux-Umgebung laufenden PHP-Interpreter. == Voraussetzungen zum Arbeiten mit Firebird unter PHP == Die erste Voraussetzung fuer das Arbeiten mit Firebird unter PHP ist ein vorhandener und funktionierender Firebird-Server mit mindestens einem Datenbankschema und einem eingerichteten User. Dokumentationen und Tutorials fuer die Installation des Servers finden sich auf der [http://www.firebirdsql.org Firebird-Website]; alternativ gibt es dazu ein gutes und kurzes englischsprachiges [http://www.debianhelp.co.uk/firebird.htm Tutorial] auf debianhelp.co.uk. Neben dem eigentlichen Server wird das PHP-Modul <i>interbase</i> benoetigt. Dieses laesst sich fuer gewoehnlich komfortabel ueber den von Ihrer Distribution eingesetzten Paketmanager installieren. aptitude/apt-get kennen das Interbase-Modul beispielsweise als <i>php5-interbase</i>: <syntaxhighlight lang=bash> sudo apt-get install php5-interbase </syntaxhighlight> Wenn diese Kriterien erfuellt sind, braucht PHP im jeweiligen Skript eine Verbindung zur Firebird-Datenbank. Diese Verbindung werden wir im folgenden Schritt aufbauen. Jede Funktion, die das Modul <i>Interbase</i> zur Verfuegung stellt, beginnt mit <code>ibase_</code>. Dieser Praefix ist eine Referenz auf die oben erwaehnte, aeltere, Interbase-Datenbank, von der Firebird abstammt. Um eine Verbindung aufzubauen nutzen wir das Kommando <code>ibase_connect</code>. Es erwartet vier Parameter: Einen Connectionstring, der den Hostname und den Pfad zur Datenbankdatei angibt, einen Usernamen, ein Passwort, und einen String, der das Encoding angibt. Der Connectionstring ist folgendermassen aufgebaut: <i>host</i>:/<i>pfad</i>/<i>zur</i>/<i>datenbank.fdb</i> Wenn wir davon ausgehen, dass der Datenbankserver, den wir ansprechen wollen auf demselben Server liegt, wie unsere PHP-Umbebung und davon, dass die Datenbankdatei, auf der wir arbeiten wollen in /var/lib/firebird/2.5/data/testdatenbank.fdb liegt, und wir bereits einen User <i>testuser</i> mit dem Passwort <i>testpassword</i> angelegt haben, so wuerden wir die Datenbankverbindung wie folgt aufbauen: <syntaxhighlight lang=php> $handle = ibase_connect('localhost:/var/lib/firebird/2.5/data/testdatenbank.fdb','testuser','testpassword','UTF-8'); </syntaxhighlight> Nach dem Ausfuehren dieses Statements finden wir in $handle ein Handle auf die Datenbankverbindung. Wir werden es in Zukunft <code>ibase_</code>-Operationen mitgeben, die auf dieser Datenbankverbindung arbeiten sollen. == Firebird abfragen unter PHP == Firebird beherrscht grundsaetzlich zwei Mechanismen um Abfragen zu verarbeiten: Den simplen <i>ibase_query</i> und kompilierte Statements via <code>ibase_prepare</code> und <code>ibase_execute</code>. Wenn ein Statement nur einmal ausgefuehrt werden soll, genugt <code>ibase_query</code>. Soll jedoch ein Statement mehrmals mit unterschiedlichen Parametern ausgefuehrt werden, so empfiehlt es sich, den <code>ibase_prepare</code>-Mechanismus zu nutzen um ein performanteres Skript zu erhalten. Betrachten wir zunaechst die Methode <code>ibase_query</code>. Ein typischer Aufruf koennte beispielsweise so aussehen (Ich gehe davon aus, dass wir in <code>$handle</code> mit <code>ibase_connect</code> eine valide Verbindung aufgebaut haben): <syntaxhighlight lang=php> $result = ibase_query($handle,"SELECT * FROM Testtabelle;"); </syntaxhighlight> In <code>$result</code> ist nun das Ergebnis der Abfrage gespeichert. Es ist eine Liste aus 0-n Datensaetzen, aus der wir nun die einzelnen Datensaetze extrahieren koennen. Dazu spaeter mehr. Betrachten wir nun die Abfrage mittels prepare/execute: <syntaxhighlight lang=php> $statement = ibase_prepare($handle,"SELECT * FROM Testtabelle;"); $result = ibase_execute($statement); </syntaxhighlight> Da eine Abrage mit prepare/execute ohne Parameter praktisch keinen Sinn ergibt, folgen nun zwei Beispiele fuer Abfragen mit Parametern. Query: <syntaxhighlight lang=php> $result = ibase_query($handle,"SELECT * FROM Testtabelle WHERE Feld1 = ?;", 'testwert'); </syntaxhighlight> Prepare/Execute: <syntaxhighlight lang=php> $statement = ibase_prepare($handle,"SELECT * FROM Testtabelle WHERE Feld1 = ?;"); $result = ibase_execute($statement, 'testwert'); </syntaxhighlight> Wie wir sehen, nehmen die Funktionen <code>ibase_execute</code> und <code>ibase_query</code> die Parameter fuer das Statement einfach zusaetzlich als Uebergabeparameter an. == Extrahieren von Daten aus dem Recordset == Um tatsaechlich in PHP verwendbare Daten aus dem Recordset zu Gewinnen, stellt <i>interbase</i> drei Funktionen zur Verfuegung: <code>ibase_fetch_object</code>, <code>ibase_fetch_assoc</code>, <code>ibase_fetch_row</code>. In den folgenden Beispielen gehe ich davon aus, dass bereits ein wie oben beschriebenes <code>$result</code> zur Verfuegung steht. <code>ibase_fetch_object</code> erzeugt ein PHP-Objekt aus einem Datensatz: <syntaxhighlight lang=php> $object = ibase_fetch_object($result); $a = $object->Feld1; echo $a; // $a ist nun der Wert des Feldes "Feld1" im aktuellen Datensatz der Tabelle "Testtabelle" </syntaxhighlight> <code>ibase_fetch_assoc</code> erzeugt ein assoziatives Array aus einem Datensatz: <syntaxhighlight lang=php> $array = ibase_fetch_assoc($result); $a = $array['Feld1']; echo $a; // $a ist nun der Wert des Feldes "Feld1" im aktuellen Datensatz der Tabelle "Testtabelle" </syntaxhighlight> <code>ibase_fetch_row</code> erzeugt ein einfaches Array aus einem Datensatz: <syntaxhighlight lang=php> $array = ibase_fetch_row($result); $a = $array[0]; echo $a; // $a ist nun der Wert des Feldes "Feld1" im aktuellen Datensatz der Tabelle "Testtabelle" </syntaxhighlight> Alle drei genannten Methoden inkrementieren den internen Datensatz-Pointer des Resultsets. Und geben FALSE zurueck, falls keine Datensaetze mehr verfuegbar sein sollten. Das hat zur Folge, dass wir Abfrageergebnisse sehr einfach in Schleifen bearbeiten koennen: <syntaxhighlight lang=php> while($object = ibase_fetch_object($result)){ echo $object->Field1; //mache irgendwas mit $object } </syntaxhighlight> == Sequenzen == Firebird unterstuetzt Sequenzen. Squenzen sind essentiell um beispielsweise fortlaufende IDs fuer Datensaetze zu generieren. Das <i>Interbase</i>-Modul unterstuetzt hierfuer die Funktion <code>ibase_gen_id</code>, die eine Sequenz um 1 inkrementiert und deren neuen Wert zurueckgibt. Als Parameter erwartet sie den Bezeichner der Sequenz. In der Praxis sieht das so aus: <syntaxhighlight lang=php> $id = ibase_gen_id('Testsequenz'); echo $id; // $id enthaelt den neuen um 1 inkrementierten Wert der Sequenz 'Testsequenz' </syntaxhighlight> Mit <code>ibase_gen_id</code> laesst sich eine Sequenz auch um einen beliebigen Integerwert hochzaehlen. Das sieht so aus: <syntaxhighlight lang=php> $id = ibase_gen_id('Testsequenz',5); echo $id; // $id enthaelt den neuen um 5 inkrementierten Wert der Sequenz 'Testsequenz' </syntaxhighlight> <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: PostgreSQL]] [[Websiteentwicklung: PHP: PostgreSQL|Vor zu PostgreSQL]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = PostgreSQL= == Kurze Einführung in PostgreSQL == PostgreSQL ist eine OpenSource-Datenbank, die um anspruchsvolle Unternehmenslösungen sowie hohe Ansprüche an Skalierbarkeit und Performance bemüht ist. Die Entwicklung wird von einer Vielzahl von Personen auf der ganzen Welt vorangetrieben. Es steht jedoch keine Firma mit kommerziellem Interesse hinter dem Projekt. Großer Wert wird auf Datensicherheit und die Einhaltung von Standards der Datenbank gelegt. Die Installation kann sowohl unter Linux/Unix-artigen Betriebssystemen als auch unter Windows oder Mac OS X erfolgen. == PostgreSQL in PHP == PHP bietet auch für PostgreSQL eine Vielzahl an Funktionen, um mit dem Datenbanksystem zu kommunizieren. Hier eine Auswahl der Funktionen: * PG_CONNECT baut eine neue Verbindung zur PostgreSQL-Datenbank auf. Die Angabe der Parameter im connection_string sind optional, d.h. es werden bei fehlenden Angaben die Standardwerte gesetzt.Er kann einen oder mehrere Parameter, durch Leerzeichen getrennt, enthalten. Jeder Parameter muss in der Form keyword = value angegeben werden. Um einen leeren Wert oder einen Wert, welcher Leerzeichen enthält, zu übergeben, muss dieser in einfache Anführungszeichen eingeschlossen sein. Bei erfolgreicher Verbindung wird eine Verbindungskennung zurückgegeben, bei einem Fehler FALSE. Wird ein zweiter Aufruf von pg_connect mit den gleichen Parametern durchgeführt, so wird die Verbindungskennung der bereits geöffneten Verbindung zurückgegeben. Es sei denn, der Parameter connection_type enthält die Konstante PGSQL_CONNECT_FORCE_NEW. Dies bewirkt, dass eine neue Verbindung zur Datenbank aufgebaut wird. pg_connect("string connection_string [int connect_type]"); ''Beispiel: $dbconn = pg_connect("host=localhost dbname=testdb user=muster password=test"); <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Templates= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Templates]] [[Websiteentwicklung: PHP: Templates|Templates]] </div> Templates oder <span style="white-spaces: nowrap;"><span class="noprint">[[Bild:Wikipedia-logo-v2.svg|17px|link=w:Template_Engine|alt=]]</span>&nbsp;[[w:Template_Engine|Template Engines]]</span> gelten als Variante, um HTML und PHP voneinander zu trennen. Dabei werden in eine <span style="white-spaces: nowrap;"><span class="noprint">[[Bild:Wikipedia-logo-v2.svg|17px|link=w:HTML|alt=]]</span>&nbsp;[[w:HTML|HTML]]</span>-Vorlage (engl. "Template" für "Schablone") Markierungen gesetzt, an denen das Script dynamisch Inhalte einsetzen kann. Diese werden ''Platzhalter'' oder ''Templatevariablen'' genannt. Das können bei einem Forum die Titel der Themen sein, die es aus einer Datenbank geholt werden. Oder über ein Template und PHP wird eine HTML-Mail generiert. Das Template ist in diesem Fall nur für das Aussehen des Mail verantwortlich. Die Daten werden vom PHP-Skript zur Verfügung gestellt. Wie man unter <span style="white-spaces: nowrap;"><span class="noprint">[[Bild:Wikipedia-logo-v2.svg|17px|link=w:Template_Engine|alt=]]</span>&nbsp;[[w:Template_Engine|Template Engine]]</span> nachlesen kann, bilden PHP-Skript und Template eine Einheit. Die <span style="white-spaces: nowrap;"><span class="noprint">[[Bild:Wikipedia-logo-v2.svg|17px|link=w:Template_Engine#Vorteile|alt=]]</span>&nbsp;[[w:Template_Engine#Vorteile|Vorteile von Templates]]</span> sind, dass Designer und Coder unabhängig voneinander arbeiten können, ohne die konkreten Inhalte kennen zu müssen und dass der grafische Aufbau schnell und unkompliziert bei allen betroffenen Seiten geändert werden kann. Der Nachteil ist, dass sich Coder und Designer, solange es sich nicht um eine Person handelt, auf eine gemeinsame Schnittstelle einigen müssen, damit der Coder weiß, an welcher Stelle die Inhalte einzufügen sind und der Designer weiß welche und wieviele Markierungen er setzen muss und was diese später einfügen. Templates lassen sich oft schachteln, so dass in ein Template andere Templates eingefügt werden können. So lassen sich verschieden komplexe Seitengestaltungen auf eine oder mehrere übergeordnete Grundschemen zurückführen. Es ist mit Templates einfacher Webseiten <span style="white-spaces: nowrap;"><span class="noprint">[[Bild:Wikipedia-logo-v2.svg|17px|link=w:Modulare_Programmierung|alt=]]</span>&nbsp;[[w:Modulare_Programmierung|modular aufzubauen]]</span> und macht sowohl den Quelltext von PHP und HTML übersichtlicher. == Verschiedene Template Engines == * [[Websiteentwicklung:_PHP:_Smarty|Smarty]] * [[Websiteentwicklung:_PHP:_vlibTemplate|vlibTemplate]] * [[Websiteentwicklung:_PHP:_SKOR PHP Template|SkOR PHP Template]] * [[Websiteentwicklung:_PHP:_TinyButStrong|TinyButStrong (TBS)]] * [[Websiteentwicklung:_PHP:_EasyTemplateSystem|easy template system (ETS)]] == Weblinks == Der Bereich ''Weblinks'' ist in Bereiche aufgeteilt: === Beispiele === * [http://lamp.clausvb.de/smarty_examples/basic.php Smarty: Einfaches Beispiel] * [http://lamp.clausvb.de/smarty_examples/db.php Smarty: Datenbankzugriff] * [http://lamp.clausvb.de/vlib_examples/basic.php vlibTemplate: Einfaches Beispiel] * [http://lamp.clausvb.de/vlib_examples/db.php vlibTemplate: Datenbankzugriff] * [http://lamp.clausvb.de/tbs_examples/basic.php TinyButStrong: Einfaches Beispiel] * [http://lamp.clausvb.de/tbs_examples/db.php TinyButStrong: Datenbankzugriff] === Kritik an Template engines === * [http://www.pberndt.com/_Newsdata/leserbrief_iX_0706.txt] * [http://www.codeassembly.com/Why-template-systems-like-smarty-are-useless-and-sometimes-bad/] * [http://de.wikipedia.org/wiki/Template_Engine#PHP_Template_Engines 1. Absatz] * [http://michaelbertsch.eu/blog/minimalistische-template-engine-fuer-php] === Dokumentationen und Tutorials === * [http://tut.php-q.net/template.html Smarty: Installation und erste Schritte] * [http://smarty.php.net/crashcourse.php Smarty: Crash-Kurs (englisch)] * [http://lamp.clausvb.de/smarty_mhtml/table_of_content.html Smarty: Tutorial] * [http://lamp.clausvb.de/index/menuid/140/ vlibTemplate: Einführung] * [http://lamp.clausvb.de/vlib_mhtml/table_of_content.html vlibTemplate: Tutorial] * [http://vlib.clausvb.de/docs/multihtml/vlibtemplate/table_of_content.html vlibTemplate: Befehlsreferenz (englisch)] * [http://lamp.clausvb.de/index/menuid/144/ TinyButStrong: Einführung] * [http://lamp.clausvb.de/tbs_mhtml/table_of_content.html TinyButStrong: Tutorial] * [http://lamp.clausvb.de/tbs_mhtml/tbs_de_manual.htm TinyButStrong: Befehlsreferenz] === Foren === * [https://sebastiany.net/php-template.html SKOR php template] * [http://www.phpinsider.com/smarty-forum/viewforum.php?f=17 Smarty] * [http://vlib.clausvb.de/forum/index.php?showforum=3 vlibTemplate] * [http://www.tinybutstrong.com/forum.php TinyButStrong] <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung:_PHP:_Fehlerquellen]] [[Websiteentwicklung:_PHP:_Fehlerquellen|Zurück zu Fehlerquellen]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung:_PHP]] [[Websiteentwicklung:_PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung:_PHP:_PEAR]] [[Websiteentwicklung:_PHP:_PEAR|Vor zu PEAR]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Smarty= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Templates]] [[Websiteentwicklung: PHP: Templates|Templates]][[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Smarty]] [[Websiteentwicklung: PHP: Smarty|Smarty]] </div> <span style="white-spaces: nowrap;"><span class="noprint">[[Bild:Wikipedia-logo-v2.svg|17px|link=w:Template Engine|alt=]]</span>&nbsp;[[w:Template Engine|Template Engine]]</span> für PHP http://www.smarty.net siehe auch <span style="white-spaces: nowrap;"><span class="noprint">[[Bild:Wikipedia-logo-v2.svg|17px|link=w:Smarty|alt=]]</span>&nbsp;[[w:Smarty|den Wikipedia Artikel]]</span> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = vlibTemplate= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Templates]] [[Websiteentwicklung: PHP: Templates|Templates]][[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: vlibTemplate]] [[Websiteentwicklung: PHP: vlibTemplate|vlibTemplate]] </div> '''vlibTemplate''' ist eine <span style="white-spaces: nowrap;"><span class="noprint">[[Bild:Wikipedia-logo-v2.svg|17px|link=w:Template Engine|alt=]]</span>&nbsp;[[w:Template Engine|Template Engine]]</span>, die in <span style="white-spaces: nowrap;"><span class="noprint">[[Bild:Wikipedia-logo-v2.svg|17px|link=w:PHP|alt=]]</span>&nbsp;[[w:PHP|PHP]]</span> geschrieben wurde. Die PHP-Klasse, soll die Trennung von PHP- und <span style="white-spaces: nowrap;"><span class="noprint">[[Bild:Wikipedia-logo-v2.svg|17px|link=w:HTML|alt=]]</span>&nbsp;[[w:HTML|HTML]]</span>-Code zu einer einfachen und natürlichen Sache machen. vlibTemplate benutzt die folgenden "markup tags": <tmpl_var>, <tmpl_loop>, <tmpl_include>, <tmpl_if> und andere. Eine Datei, die solche Tags enthält nennt man Template. Ein Template kann eine HTML-Datei sein, um sie im Web zu benutzen oder eine Textdatei, die als E-Mail versendet wird ... es gibt viele Möglichkeiten. Die Templatedatei wird immer separat vom PHP-Skript (das es benutzt/aufruft) abgespeichert, so kann ein <span style="white-spaces: nowrap;"><span class="noprint">[[Bild:Wikipedia-logo-v2.svg|17px|link=w:Webdesign|alt=]]</span>&nbsp;[[w:Webdesign|Webdesigner]]</span> zum Beispiel das Template ändern ohne den ganzen PHP-Code durchgehen zu müssen. Die Klasse versetzt Sie in die Lage, Design und Daten, die Sie mit PHP erzeugen, zu trennen. vlibTemplate ist ein Teil der Klasse ''vLIB''. Es gibt eine <span style="white-spaces: nowrap;"><span class="noprint">[[Bild:Wikipedia-logo-v2.svg|17px|link=w:Schnittstelle|alt=]]</span>&nbsp;[[w:Schnittstelle|Schnittstelle]]</span> zu ''vlibDate'' und ''vlibMimeMail''. Sie können leistungsstarke <span style="white-spaces: nowrap;"><span class="noprint">[[Bild:Wikipedia-logo-v2.svg|17px|link=w:Webanwendung|alt=]]</span>&nbsp;[[w:Webanwendung|Webanwendungen]]</span> mit vLIB erstellen. == Beispiel für <span style="white-spaces: nowrap;"><span class="noprint">[[Bild:Wikipedia-logo-v2.svg|17px|link=w:Quelltext|alt=]]</span>&nbsp;[[w:Quelltext|Quelltext]]</span> == Da vlibTemplate PHP von HTML trennt, gibt es zwei Dateien: <syntaxhighlight lang="html4strict"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html> <head> <title>{tmpl_var name='title_text'}</title> <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" /> </head> <body> <p>{tmpl_var name='body_text'}</p> </body> </html></syntaxhighlight> Wie Sie sehen können, enthält diese Datei bzw. das Template nur HTML und die oben erwähnten "markup tags". Hier wird TMPL_VAR verwendet. TMPL_VAR bildet die Schnittstelle zum PHP-Skript: <syntaxhighlight lang="php">require_once 'vlib/vlibTemplate.php'; $tmpl = new vlibTemplate('tmpl/basic.htm'); $tmpl->setvar ('title_text', 'TITLE: This is the vLIB basic example ...'); $tmpl->setvar ('body_text', 'BODY: This is the message set using setvar'); $tmpl->pparse;</syntaxhighlight> Es können sogar sehr komplizierte Designs mit vlibTemplate umgesetzt werden. Um den Prozess des <span style="white-spaces: nowrap;"><span class="noprint">[[Bild:Wikipedia-logo-v2.svg|17px|link=w:Parser|alt=]]</span>&nbsp;[[w:Parser|Parsens]]</span> zu beschleunigen, kann ''vlibTemplateCache'' benutzt werden. == Features == * Trennung von PHP und HTML * '''<span style="white-spaces: nowrap;"><span class="noprint">[[Bild:Wikipedia-logo-v2.svg|17px|link=w:WYSIWYG|alt=]]</span>&nbsp;[[w:WYSIWYG|WYSIWYG]]</span>''': Sie können Ihre Templates mit <span style="white-spaces: nowrap;"><span class="noprint">[[Bild:Wikipedia-logo-v2.svg|17px|link=w:Microsoft_FrontPage|alt=]]</span>&nbsp;[[w:Microsoft_FrontPage|Frontpage]]</span>, <span style="white-spaces: nowrap;"><span class="noprint">[[Bild:Wikipedia-logo-v2.svg|17px|link=w:Dreamweaver|alt=]]</span>&nbsp;[[w:Dreamweaver|Dreamweaver]]</span> oder allen anderen <span style="white-spaces: nowrap;"><span class="noprint">[[Bild:Wikipedia-logo-v2.svg|17px|link=w:WYSIWYG|alt=]]</span>&nbsp;[[w:WYSIWYG|WYSIWYG]]</span>- oder <span style="white-spaces: nowrap;"><span class="noprint">[[Bild:Wikipedia-logo-v2.svg|17px|link=w:Texteditor|alt=]]</span>&nbsp;[[w:Texteditor|Texteditoren]]</span>, die Sie sich vorstellen können erstellen. * modularer Aufbau von HTML-Seiten mit TMPL_INCLUDE * '''Loops / Blöcke''': Immer wiederkehrende Daten ausgeben * '''Datenbankloops''': Daten aus einer DB (MySQL, Oracle, Informix, etc.) direkt ausgeben * IF-Abfragen in Templates * '''Template Caching''': Seiten cachen * '''Template Debugger''': Ansicht aller Templatevariablen und -Loops. Mächtiges Werkzeug um alle Fehler zu finden. == External links == * [http://lamp.clausvb.de/ vLIB] * [http://sourceforge.net/project/showfiles.php?group_id=43712&package_id=36066 Download] * [http://dl.clausvb.de/view_file.php?id=7 Download der vLIB-Beispiele] * [http://vlib.clausvb.de/docs/multihtml/vlibtemplate/table_of_content.html Dokumentation und Befehlsreferenz (englisch)] * [http://lamp.clausvb.de/vlib_mhtml/table_of_content.html Einführung und Tutorial (deutsch)] * [http://vlib.clausvb.de/forum/index.php?showforum=1 Englisches Forum] * [http://vlib.clausvb.de/forum/index.php?showforum=3 Deutsches Forum] * [http://vlib.clausvb.de/benchmarks/ Benchmarks] <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Zend Framework 2 = Das [[w:Zend Framework|Zend Framework 2]] ist ein objektorientiertes PHP Framework von [[w:Zend Technologies|Zend Technolgies]]. Es ist nicht abwärtskompatibel zum Zend Framework 1 und benötigt zu mindestens die [[w:PHP|PHP]] Version 5.3.3. == Bücher == * [http://www.zendframeworkbuch.de/ Zend Framework 2: Von den Grundlagen bis zur fertigen Anwendung] von Ralf Eggert (Addison Wesley) * [https://leanpub.com/zendframework2 Webentwicklung mit Zend Framework 2] von Michael Romer * [http://www.galileocomputing.de/katalog/buecher/titel/gp/titelID-3460 Zend Framework 2: Webanwendungen mit dem PHP-Framework] (Nur Angekündigt) von Ralf Eggert (Galileo Computing) == Weblinks == * [http://framework.zend.com/manual/ http://framework.zend.com/manual/] Eine kleine Einführung in das ZF2 und eine Referenz auf der offiziellen Seite. <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = CakePHP= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: CakePHP]] [[Websiteentwicklung: PHP: CakePHP|CakePHP]] </div> [[File:Cake.logo.png|thumb|CakePHP Logo]] == Was ist CakePHP? == CakePHP selbst versteht sich als MVC-Framework für schnellere oder - in diesem Kontext auch - agilere Webserviceprogrammierung. Dabei wirkt CakePHP wie eine weitere Applikationsschicht, auf der man letztenendes programmieren kann. MVC steht für Model-View-Controller und definiert drei unterschiedliche Bereiche, die miteinander kommunizieren und bestimmte Dienste zur Verfügung stellen. Das Model bietet den Zugang zu externen Datenquellen wie Datenbanken oder APIs. Der View ist darauf spezialisiert die - eventuell gefilterten und bearbeiteten - Daten an den Browser weiter zu leiten. Der Controller ist die Schaltzentrale jeder Cake-Anwendung und verbindet das Model mit dem View. CakePHP folgt zusätzlich einigen Richtlinien, die beim Einsatz durch Frameworks zum tragen kommen: * '''CoC''': Convention over configuration * '''DRY''': Don't repeat yourself * '''CRUD''': CREATE, READ, UPDATE, DELETE == Namenskonventionen == Durch Namenskonventionen beschleunigt CakePHP die Entwicklung einer Anwendung. An einigen Stellen reicht es, wenn bestimmte Elemente einer gewissen Konvention entsprechen. Diese werden für andere Elemente durch die Einhaltung der Konvention automatisch sichtbar und müssen nicht gesondert konfiguriert werden. === Dateinamen und Klassen === Dateien werden mit unterstrichen geschrieben, während dazugehörige Klassennamen groß und klein geschrieben werden. Eine Klasse, die ''MySuperController'' heißen soll, wird daher in einer Datei Namens ''my_super_controller.php'' gespeichert. === Model und Datenbanken === Models werden im Singular notiert und entsprechen der Tabellenbezeichung aus der genutzten Datenbank. Eine Tabelle namens ''user'' wird als Model in CakePHP als Klasse ''User'' in der Datei ''user.php'' im ''models'' Ordner gespeichert. Tabellenverknüpfungen werden automatisch erkannt, sobald die Einträge in der Tabelle einem gewissen Muster entsprechen. Ein Beispiel wäre die ''hasMany'' Verknüpfung zwischen ''document'' und ''tag''. Ein Dokument kann also mehrere Tags haben. In der Tags-Tabelle wird dafür ein Fremdschlüssel auf die Spalte ''document_id'' gelegt. === Controller === Jedes Model benötigt standardmäßig einen Controller. Dieser ist immer im Plural zu benennen. Für das Beispiel-Model ''Invoice'' würde der Controller ''InvoicesController'' heißen. CakePHP verarbeitet hier die korrekte Mehrzahlangabe, zumindest für die englische Sprache. Ebenfalls ist CakePHP in der Lage dem Model ''Callory'' den Controller ''CalloriesController'' zuzuweisen. === View === Jeder Controller erhält unterschiedliche Views. Je nachdem welche Methoden ein Controller besitzt (Beispiel: index) gibt es auch dementsprechende Views. Diese Views werden, für das Beispielmodel ''User'' mit dem Controller ''UsersController'' im Ordner ''app/views/users/index.ctp''. Die Verarbeiteten Daten in der Methode ''index'' im Controller werden im View index.ctp im Anschluss für den Browser in HTML gepackt. Besitzt ein Controller mehrere Methoden, die unterschiedliche Ausgaben haben müssen, lassen sich alle Views gemeinsam im entsprechenden Ordner ablegen. == Architektur == [[File:Cakephp Schema Einfach.png|thumb|Cakephp Schema - Einfach]] === Model === Das Model stellt die Verbindung zur Datenquelle bereit. Diese kann je nach Typ variieren und wird in der Datei app/config/database.php eingetragen. Jedes Model in CakePHP stellt einen Zugang zu einer Tabelle in einer Datenbank bereit, vorausgesetzt, die Datenquelle ist eine Datenbank. Das Model bietet allerdings noch einige andere Features: * Bezug von Daten aus einer Datenquelle * Bereitstellung der Daten für den Controller * Validierung eingegebener Daten * Daten in der Datenbank erstellen, erneuern, löschen * Verknüpfungen zu anderen Modellen aufbauen ==== Bezug von Daten ==== Das Model bietet zur Datenabfrage die Methode ''find''. Diese erzeugt intern die nötigen SQL Befehle, um die Anweisungen des Programmieres in die Tat umzustzen. Die Methode unterstützt folgende Parameter: * '''all''': Gibt alle Datensätze zurück, die mit den zusätzlich übergebenen Parametern übereinstimmen * '''first''': Gibt nur das erste Ergebnis zurück * '''count''': Gibt nur die Anzahl an Ergebnissen zurück, die bei den Bedingungen gefunden worden ist * '''list''': Gibt alle Datensätze zurück, ähnlich wie all, allerdings werden diese in Key-Value-Paare ausgegeben * '''neighbours''': Gibt die benachbarten Datensätze zurück ==== Bereitstellung der Daten ==== Die Darstellung der Daten innerhalb eines Modells findet innerhalb eines mehrdimensionalen Arrays statt. Folgende Beispieltabelle liegt vor: {| class="wikitable" |- ! id !! name !! email !! status |- | 1 || defc0n || defc0n(at)foobar.com || 1 |- | 2 || mitm || mitm(at)foobar.com || 0 |} Diese Daten würden im Modell wie folgt dargestellt werden: <syntaxhighlight lang="PHP"> [User] => Array ( [0] => Array ( [id] => 1 [name] => defc0n [email] => defc0n(at)foobar.com [status] => 1 ) [1] => Array ( [id] => 2 [name] => mitm [email] => mitm(at)foobar.com [status] => 0 ) ) </syntaxhighlight> ==== Validierung von Daten ==== Viele Webapplikationen nutzen Formulare, die auf der Serverseite geprüft werden müssen. Darunter fallen beispielsweise E-Mail Adressen, Kreditkarten-Nummern oder es soll ein Datum eingegeben werden. Erfahrene Nutzer würden wohl als erstes an reguläre Ausdrücke denken. Dieses hat CakePHP bereits integriert, lässt aber auch eigene Kreationen zu. Die Validierung erfolgt im Model innerhalb der ''validate'' Variable und wird als mehrdimensionales Array dargestellt. Beispielsweise gibt es ein Formular, welches ein Datum vom Benutzer entgegen nehmen soll. Das Feld, in dem das Datum eingetragen wird, heißt '''meinDatum'''. Dazu lässt sich die Variable validate wie folgt befüllen: <syntaxhighlight lang="PHP"> var $validate = array( 'meinDatum' => 'date' ); </syntaxhighlight> Es können auch Fehlermeldungen angepasst werden, die automatisch angezeigt werden: <syntaxhighlight lang="PHP"> var $validate = array( 'meinName' => array( 'rule' => false, 'required' => true, 'message' => 'Bitte geben Sie einen Namen ein!' ), ); </syntaxhighlight> ==== Datenbank Manipulation ==== ==== Verknüpfungen zu anderen Modellen ==== === View === === Controller === == Erweiterte Architektur == [[File:Cakephp Schema Erweitert.png|thumb|Add caption here]] Die Architektur von CakePHP erlaubt einige Module selber zu erstellen, die wieder genutzt werden. Ganz nach dem Motto '''Don't repeat yourself!''' lassen sich Controller, Model, View und sogar ganze Applikationen erweitern. Die Erweiterungen des Controllers nennen sich Components. Die des Models sind die Behaviours und die erweiternden Module im View sind die Helper und Elements. Möchte man als Entwickler bereits geschriebene Applikationen in neuen Nutzen, so lassen sich diese als Plugins wieder verwenden. Man sollte allerdings darauf achten, dass man für diesen Fall seine Module auch als Plugins entwickelt, so dass kein zusätzlicher Programmieraufwand entsteht. === Components === Components sind Bauteile, die dem Controller angehören. Sie befinden sich innerhalb des '''controllers''' Ordner in einem eigenen Ordner namens '''components'''. Innerhalb eines Controllers kann man auf Components nur zugreifen, wenn dies explizit angegeben ist: <syntaxhighlight lang="PHP"> var $components = array('MyTestComponent1', 'MyTestComponent2'); function index { if($this->MyTestComponent2 == true) echo "Component1 funktioniert"; } </syntaxhighlight> Ein Component Objekt selbst erbt von der Klasse '''Object'''. Zusätzlich wird eine '''initialize''' Funktion eingebaut, um die Zugehörigkeit zu einem Controller zu sichern. Anschließend folgen die Methoden, die das Component-Objekt ausmachen. <syntaxhighlight lang="PHP"> class MyTestComponent2 extends Object { protected $__controller = null; function initialize(&$controller) { $this->__controller = $controller; } // Beispiel Methode public function array_add(&$array, $value) { array_push($array, $value); } } </syntaxhighlight> Man sollte darauf achten, dass eventuell übergebene Arrays als Referenz übergeben werden, da sonst der Speicherverbrauch sehr stark ansteigen könnte. === Behaviors === === Helper === === Elements === === Plugins === == Voraussetzungen == == Installation der Grundanwendung == === Grundkonfiguration === === Datenbankanbindung === === Erstes Model === * '''Datei: app/model/user.php''' <syntaxhighlight lang="php"> <?php class User extends AppModel { // Name des Models ist im Controller sichtbar var $name = 'User'; } ?> </syntaxhighlight> === Erster Controller === * '''Datei: app/controller/users_controller.php''' <syntaxhighlight lang="PHP"> <?php class UsersController extends AppController { function index { // alle Daten aus dem User Modell beziehen $users = $this->User->find('all'); // Daten im View zugänglich machen $this->set('users', $users); } } ?> </syntaxhighlight> === Erstes View === * '''Datei: app/view/users/index.ctp''' == Links == * [http://github.com/cakephp/cakephp/downloads Cake-PHP Download] (viele Versionen) * [http://book.cakephp.org/ Cake-PHP 1.3 - Manual] * [http://api13.cakephp.org/ Cake-PHP 1.3 - API] * [http://cakephp.org/files/Resources/CakePHP-1.2-Cheatsheet.pdf Cake-PHP Cheatsheet] (empfehlenswert für Anfänger) * [http://bakery.cakephp.org/ Bakery] - Download unzähliger Module <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = CLI= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: CLI]] [[Websiteentwicklung: PHP: CLI|Command Line Interface (CLI)]] </div> == PHP auf der Kommandozeile == Seit Version 4.3.0 unterstützt PHP das sogenannte Command Line Interface (CLI). Damit ist es möglich PHP-Scripte auch von der Kommandozeile auszuführen. Um das CLI benutzen zu können muß es beim Kompilieren aktiviert werden. Danach ist eine ausführbare Datei mit dem Namen php verfügbar. Um ein PHP-Script auf der Kommandozeile auszuführen kann man folgende Befehle verwenden. <pre> php scriptName.php php -f scriptName.php </pre> Linux und andere Unix artige Betriebsysteme können auch mit der Klassischen Shebang-Zeile gescriptet werden: <pre>#!/pfad/zu/php</pre> Wenn man nicht weiß wo sich PHP befindet hilft dieser Befehl: <pre>whereis php</pre> Das Script kann jetzt aufgerufen werden: <pre>./scriptName.php</pre> == Argumente == Wird ein PHP-Skript von der Kommandozeile aus aufgerufen, stehen zwei Variablen automatisch zur Verfügung: $argc und $argv. $argc ist ein Integer und gibt die Zahl der an das Skript übergebenen Argumente +1 an (der Dateiname des Skripts zählt für sich), $argv ein Array mit den Argumenten, wobei hier das erste Element der Dateiname ist. Ein einfaches Kommandozeilenskript könnte so aussehen: <syntaxhighlight lang="php"> <?php if ($argc == 1 || $argv[1] == '-help') { ?> ************************ * Kommandozeilenskript * ************************ Befehle: -help zeigt diese Hilfe an <?php } ?> </syntaxhighlight> Der obige Text wird dann sowohl beim Aufruf von <pre> php scriptName.php </pre> als auch <pre> php scriptName.php -help </pre> angezeigt. <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: PEAR]] [[Websiteentwicklung: PHP: PEAR|Zurück zu PEAR]] | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | </div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Zertifizierung= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Zertifizierung]] [[Websiteentwicklung: PHP: Zertifizierung|Zertifizierung]] </div> Die israelische Firma [http://www.zend.com/ Zend], die für die Entwicklung von PHP verantwortlich ist, bietet seit einiger Zeit auch ein [http://www.zend.com/de/store/php-certification/ Zertifizierungsprogramm für PHP-Entwickler] an. Die bestandene "Zend PHP Certification" verleiht einem den Titel "Zend Certified PHP Engineer" und kann an über 3000 Instituten auf der ganzen Welt abgelegt werden. Die Prüfung erfolgt mittels Multiple-Choice-Programm auf Englisch. Zur Vorbereitung auf die Zertifizierung werden Kurse, Handbücher und Tests angeboten. <div style="font-size:80%; border: 1px solid #dfdfdf; background-color:#F8F8FF; text-align: center;"> | [[Bild:One wikibook.svg|32px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|Hoch zu PHP]] | [[Bild:Wikibooks buchseite.svg|32px|link=Websiteentwicklung: PHP: Übungsbeispiele]] [[Websiteentwicklung: PHP: Übungsbeispiele|Vor zu Übungsbeispiele]]</div> <div style="page-break-before:always"></div> <div style="clear:both;page-break-before:always;"></div> = Übungsbeispiele= <div style=" /* Setze overflow-x: auto; um Probleme mit gefloateten Elementen zu vermeiden */ /* Siehe diese Stackoverflow-Frage: http://stackoverflow.com/questions/23897328/consider-floated-elements-for-the-width-of-blocks */ overflow-x: auto; /* Setzen der clear-Eigenschaft */ /* Zusätzliches CSS */ /* margin-top und margin-bottom wie aktuell bei p-Tags setzen */ margin-top: 0.5em; margin-bottom: 0.5em; /* Definieren des CSS für die einzelnen Styles (padding wird später definiert) */ border:1px #AAA solid; /* Definitions von font-size */ /* Definieren des Paddings */ padding: 0.35em 0.8em; /* Setzen der grundlegenden CSS-Eigenschaften für {{{position}}} */ /* Setzen von max-width (in Abhängigkeit von {{{position}}}) width überschreibt bei gesetztem Wert den Wert für max-width*/ /* Setzen von width (in Abhängigkeit von {{{position}}}) */ /* Setzen von min-width */ /* Padding+Border mit in die Width-Anweisung über die CSS3-Eigenschaft „box-sizing” aufnehmen */ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; -khtml-box-sizing: border-box; font-size: 80%; " class=" " > [[Bild:Nuvola apps bookcase.svg|26px|link=Websiteentwicklung: Inhaltsübersicht]] [[Websiteentwicklung: Inhaltsübersicht|Websiteentwicklung]] [[Bild:Nuvola apps bookcase 1.svg|26px|link=Websiteentwicklung: PHP]] [[Websiteentwicklung: PHP|PHP]] [[Bild:Gnome-mime-application-x-dvi.svg|24px|link=Websiteentwicklung: PHP: Übungsbeispiele]] [[Websiteentwicklung: PHP: Übungsbeispiele|Übungsbeispiele]] </div> == Einleitung == Die Fragen bzw. Antworten wurden weder direkt aus einem der offiziellen Bücher bzw. der Internetseiten der Firma Zend oder anderer Webseiten abgeschrieben noch stammen sie aus den Prüfungs-Unterlagen. Alle Fragen und Antworten wurden nach dem Vorbild der Vorbereitungsbücher neu und eigenständig entwickelt und können dadurch nur ein grober Anhaltspunkt für die eigentlichen Prüfungsfragen darstellen. Alle Fragen und Antworten beziehen sich auf die Version 4 vom PHP (bis einschließlich 4.3.6) mit einer unveränderten php.ini. Bei Antworten die einen Funktionsnamen verlangen dürfen die Klammern nicht eingegeben werden. Außerdem sind die Groß- und Kleinschreibung (z.B.: bei Variablen) zu beachten. Es kommt durchaus vor das sich Fehler in den Scripten verstecken. Diese Fehler führen dann meist zu anderen Ergebnissen als bei einem richtigen Script. Die Fehler wurden mit Absicht eingebaut um die Aufmerksamkeit bzw. die Begabung zur Fehlersuche zu testen. Auch bei den offiziellen Prüfungsfragen sollte man unbedingt mit Fehlern in den Beispielscripten rechnen. == PHP Grundlagen == === Frage 1 === {| width="100%" cellspacing="10px" |---- valign="top" | width="50%" style="border: 1px solid #6688AA; background-color:#efefef; padding:1em;" | Wofür steht eigentlich die Abkürzung PHP heute? * A. Professional Homepage Programming * B. Public Hyper Processing * C. PHP Homepage Producer * D. PHP: Hypertext Preprocessor * E. Public Hypertext Processor | rowspan="1" width="50%" style="border: 1px solid #6688AA; background-color:#efefef; padding:1em;" valign="top"| Antwort: '''D ist richtig!''' siehe auch: * [http://www.php.net/manual/de/introduction.php PHP Einleitung] |} === Frage 2 === {| width="100%" cellspacing="10px" |---- valign="top" | width="50%" style="border: 1px solid #6688AA; background-color:#efefef; padding:1em;" | Mit welchen Tags kann man auf keinen Fall eine PHP-Block starten bzw. beenden? * A. <?= ?> * B. <{ }> * C. <?php ?> * D. <? ?> * E. <% %> | rowspan="1" width="50%" style="border: 1px solid #6688AA; background-color:#efefef; padding:1em;" valign="top"| Antwort: '''B ist richtig!''' siehe auch: * [http://www.php.net/manual/de/language.basic-syntax.php Grundlagen der Syntax] |} === Frage 3 === {| width="100%" cellspacing="10px" |---- valign="top" | width="50%" style="border: 1px solid #6688AA; background-color:#efefef; padding:1em;" | Was wird dieses Script ausgeben? <syntaxhighlight lang="php"> <?php $fooBar = 5 - 7 % 3; echo $fooBar; ?> </syntaxhighlight> * A. 5 * B. null * C. 4 * D. true * E. 3 | rowspan="1" width="50%" style="border: 1px solid #6688AA; background-color:#efefef; padding:1em;" valign="top"| Antwort: '''C ist richtig!''' Die Modulus-Funktion (%) wird zuerst ausgeführt und gibt den Rest der Division zurück also bei 7/3 bleibt der Rest 1, und 5 - 1 ergibt 4. siehe auch: * [http://www.php.net/manual/de/language.operators.arithmetic.php Arithmetische Operatoren] * [http://www.php.net/manual/de/language.operators.php#language.operators.precedence Operator-Rangfolge] |} === Frage 4 === {| width="100%" cellspacing="10px" |---- valign="top" | width="50%" style="border: 1px solid #6688AA; background-color:#efefef; padding:1em;" | Was wird dieses Script ausgeben? <syntaxhighlight lang="php"> <?php $foo = 2; $fooBar = $foo++ + 1; echo $fooBar; ?> </syntaxhighlight> * A. 2 * B. 3 * C. 4 * D. Eine Warnung * E. null | rowspan="1" width="50%" style="border: 1px solid #6688AA; background-color:#efefef; padding:1em;" valign="top"| Antwort: '''B ist richtig!''' Der Inkrementoperator ($foo++) gibt zuerst den eigentlichen Wert ($foo = 2) zurück mit dem dann die Operation $foo + 1 (also: 2+1) berechnet wird. Erst danach erhöht er die Variable $foo um eins. Das betrifft allerdings die Variable $fooBar nicht mehr da vorher der Wert ($fooBar = 3) bereits zugewiesen wurde. siehe auch: * [http://www.php.net/manual/de/language.operators.arithmetic.php Arithmetische Operatoren] * [http://www.php.net/manual/de/language.operators.increment.php Inkrement- bzw. Dekrementoperatoren] |} === Frage 5 === {| width="100%" cellspacing="10px" |---- valign="top" | width="50%" style="border: 1px solid #6688AA; background-color:#efefef; padding:1em;" | Was wird dieses Script ausgeben? <syntaxhighlight lang="php"> <?php $foo = 2; $fooBar = --$foo + 1; echo $fooBar; ?> </syntaxhighlight> * A. 2 * B. 3 * C. 4 * D. Eine Warnung * E. null | rowspan="1" width="50%" style="border: 1px solid #6688AA; background-color:#efefef; padding:1em;" valign="top"| Antwort: '''A ist richtig!''' Der Dekrementoperator (--$foo) wird vor dem Ausdruck ($foo + 1) durchgeführt dadurch entsteht folgender Term $fooBar = (2 - 1) + 1 = 2 * [http://www.php.net/manual/de/language.operators.arithmetic.php Arithmetische Operatoren] * [http://www.php.net/manual/de/language.operators.increment.php Inkrement- bzw. Dekrementoperatoren] |} === Frage 6 === {| width="100%" cellspacing="10px" |---- valign="top" | width="50%" style="border: 1px solid #6688AA; background-color:#efefef; padding:1em;" | Was wird folgendes Script ausgeben? <syntaxhighlight lang="php"> <?php echo 12.3; echo '/'; echo 12 . 3; ?> A. 123/123 B. 12.3/123 C. 12/123 D. Eine oder mehrere Warnungen E. 12.3/12.3 | Antwort: B ist richtig! In der oberen Zahl ist der Punkt ein Dezimaltrennzeichen während in der untersten Zeile zwei ints durch den Verkettungsoperator . in strings umgewandelt und zusammengefügt werden. |
* Druckversion des Buches Name des Buches
* Dieses Buch umfasst derzeit etwa ? DIN-A4-Seiten einschließlich Bilder.
* Wenn Sie dieses Buch drucken oder die Druckvorschau Ihres Browsers verwenden, ist diese Notiz nicht sichtbar.
* Zum Drucken klicken Sie in der linken Menüleiste im Abschnitt „Drucken/exportieren“ auf Als PDF herunterladen.
* Mehr Informationen über Druckversionen siehe Hilfe:Fertigstellen/ PDF-Versionen.
* Hinweise:
* Für einen reinen Text-Ausdruck kann man die Bilder-Darstellung im Browser deaktivieren:
* Internet-Explorer: Extras > Internetoptionen > Erweitert > Bilder anzeigen (Häkchen entfernen und mit OK bestätigen)
* Mozilla Firefox: Extras > Einstellungen > Inhalt > Grafiken laden (Häkchen entfernen und mit OK bestätigen)
* Opera: Ansicht > Bilder > Keine Bilder
* Texte, die in Klappboxen stehen, werden nicht immer ausgedruckt (abhängig von der Definition). Auf jeden Fall müssen sie ausgeklappt sein, wenn sie gedruckt werden sollen.
* Die Funktion „Als PDF herunterladen“ kann zu Darstellungsfehlern führen.