Websiteentwicklung: PHP/ Druckversion

Aus Wikibooks
Zur Navigation springen Zur Suche springen
Websiteentwicklung: PHP



Wikibooks

Inhaltsverzeichnis

Websiteentwicklung: PHP: Praktische Einführung: Vorwort

Websiteentwicklung PHP Praktische Einführung Vorwort

Konzept[Bearbeiten]

  • 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[Bearbeiten]

Warum alles zweimal?[Bearbeiten]

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?[Bearbeiten]

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[Bearbeiten]

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[Bearbeiten]

Wikibooks hat das Lehrbuch:


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[Bearbeiten]

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?[Bearbeiten]

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[Bearbeiten]

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.

One wikibook.svg Hoch zu PHP | Vor zu PHP einrichten Wikibooks buchseite.svg


Websiteentwicklung: PHP: Praktische Einführung: PHP einrichten

Websiteentwicklung PHP Praktische Einführung PHP einrichten

Wie PHP funktioniert[Bearbeiten]

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:

PHP funktionsweise.png

  • 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[Bearbeiten]

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[Bearbeiten]

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

<?php

phpinfo();

?>

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[Bearbeiten]

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[Bearbeiten]

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.

Wikibooks buchseite.svg Zurück zu Vorwort | One wikibook.svg Hoch zu PHP | Wikibooks buchseite.svg Vor zu Erste Schritte


Websiteentwicklung: PHP: 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:

<html>
  <head>
    <title>Erste Schritte</title>
  </head>
  <body>
    <p><?php echo 'Hallo Welt!'; ?></p>
  </body>
</html>

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:

 Hallo Welt!
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.

Die selbe 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[Bearbeiten]

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:

<html>
  <head>
    <title><?php echo 'Mehrere PHP-Tags'; ?></title>
  </head>
  <body>
    <p><?php echo 'Es gibt nun mehrere PHP-Tags.'; ?></p>
  </body>
</html>
Den Themenbereich PHP-Tags vertiefen...


Kommentare[Bearbeiten]

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.

Den Themenbereich Kommentare vertiefen...


Der Code im Detail[Bearbeiten]

Sehen wir uns den Code einmal genau an:

<?php

echo 'Hallo Welt!';

?>

Anweisungen[Bearbeiten]

Eine Anweisung in PHP endet mit einem Semikolon (;). echo 'Hallo Welt'; ist somit eine Anweisung, während

<?php

echo 'Hallo ';
echo 'Welt!';

?>

zwei Anweisungen sind. Anweisungen werden ausgeführt. Sie müssen dabei noch nicht einmal etwas Sinnvolles tun. Die Anweisung

<?php

'Hallo Welt';

?>

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[Bearbeiten]

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:

<?php

do_login('Charlie', 'geheim');
do_login('Anna', 'passwort');
do_login('Clever', '9d$22!_sb?');
do_login('Gast', '');

?>

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:

<?php

echo strlen(substr('Hallo Welt!', 0, 5));

?>

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.

Wikibooks buchseite.svg Zurück zu PHP einrichten | One wikibook.svg Hoch zu PHP | Wikibooks buchseite.svg Vor zu Variablen


Websiteentwicklung: PHP: 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:

<?php

setlocale(LC_ALL, 'de_DE@euro', 'de_DE', 'deu_deu');

?>

<html>
  <head>
    <title>Zeitfunktionen</title>
  </head>
  <body>
    <p>Heute ist <?php echo strftime('%A'); ?>.</p>
    <p>In einem Jahr ist <?php echo strftime('%A', strtotime('+1 year')); ?>.</p>
  </body>
</html>

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?[Bearbeiten]

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[Bearbeiten]

Du kannst einer Variable einen Wert mit dem Zuweisungsoperator = (einfaches Gleichheitszeichen) zuweisen. Dabei wird stets der linken Variable der rechte Wert zugewiesen:

<?php

$a = 5; // $a enthält jetzt 5
$b = 'Hallo Welt!'; // $b enthält jetzt 'Hallo Welt!'
$b = $a; // Der Wert von $b wurde durch 5 ersetzt, $a bleibt bei 5
$b = $a = 'Hallo Welt!'; /* Zunächst wird $a 'Hallo Welt!' zugewiesen, anschließend $b
                            der Wert von $a, also auch 'Hallo Welt!' */

echo $b; // Gibt 'Hallo Welt!' aus

'Test' = $b; // Das wird einen Fehler erzeugen, da einem konstanten Wert nichts zugewiesen werden kann
?>
Achtung.svg

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[Bearbeiten]

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:

<?php

echo $text;

$text = 'Ich bin unsichtbar';

?>

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[Bearbeiten]

Wenden wir nun das Gelernte an:

<?php

setlocale(LC_ALL, 'de_DE@euro', 'de_DE', 'deu_deu');

$day_today = strftime('%A');
$timestamp_in_1_year = strtotime('+1 year'); /* diese Zwischenspeicherung ist nicht unbedingt notwendig, 
                                                  erleichtert aber den Überblick */
$day_in_1_year = strftime('%A', $timestamp_in_1_year);

?>

<html>
  <head>
    <title>Zeitfunktionen</title>
  </head>
  <body>
    <p>Heute ist <?php echo $day_today; ?>.</p>
    <p>In einem Jahr ist <?php echo $day_in_1_year; ?>.</p>
  </body>
</html>

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

Konstanten[Bearbeiten]

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:

<?php

define('APFEL',  1);
define('BANANE', 2);
define('PFIRSICH', 1);

define('APFEL', 1); // Das wird nicht funktionieren, da APFEL bereits definiert wurde

?>
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 $!):

<?php

define('TRAUBE', 3);

echo 'TRAUBE hat den Wert ';
echo TRAUBE;

?>

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:

<?php

trigger_error('Das wirft einen Hinweis.', E_USER_NOTICE);
trigger_error('Das wird eine Warnung erzeugen.', E_USER_WARNING);
trigger_error('Hier bricht das Skript ab.', E_USER_ERROR);

?>

Ausgabe (ähnlich):

Notice: Das wirft einen Hinweis. in C:\xampp\htdocs\tutorial\test.php on line 3

Warning: Das wird eine Warnung erzeugen. in C:\xampp\htdocs\tutorial\test.php on line 4

Fatal error: Hier bricht das Skript ab. in C:\xampp\htdocs\tutorial\test.php on line 5

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.
Den Themenbereich Variablen und Konstanten vertiefen...


Wikibooks buchseite.svg Zurück zu Erste Schritte | One wikibook.svg Hoch zu PHP | Wikibooks buchseite.svg Vor zu Templating


Websiteentwicklung: PHP: Praktische Einführung: Templating

Websiteentwicklung PHP Praktische Einführung Templating

Warum Templating?[Bearbeiten]

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

<html>
<?php mysql_connect('localhost', 'Foo', 'geheim'); ?>
  <head>
  <?php mysql_select_db('website'); ?>
  <title><?php $result = mysql_query('SELECT title FROM pages WHERE page_id = ' . (int)$_GET['page_id']);
  $row = mysql_fetch_row($result);
  echo $row[0];
  ?></title>
  </head>
  
  <body>
  <ul>
  <?php $result = mysql_query('SELECT username FROM users');
  while ($row = mysql_fetch_row($result)) {
    echo '<li>';
    echo htmlspecialchars($row[0]);
    echo '</li>';
  }
  ?>
  </ul>
  </body>
</html>

um einiges unübersichtlicher ist als

<html>
  <head>
    <title><?php echo $page['title']; ?></title>
  </head>

  <body>
    <ul>

<?php foreach($usernames as $username): ?>
      <li><?php echo htmlspecialchars($username); ?></li>
<?php endforeach; ?>

    </ul>
  </body>
</html>

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"[Bearbeiten]

Um in PHP anderen PHP-Code einzubinden, kannst du den include-Befehl verwenden:

<?php

include('my_important_functions.php');

?>
Achtung.svg

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[Bearbeiten]

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:

<?php

$title = 'Wochentage';

setlocale(LC_ALL, 'de_DE@euro', 'de_DE', 'deu_deu');

$day_today = strftime('%A');
$day_in_1_year = strftime('%A', strtotime('+1 year'));

include('templates/header.tpl.php');
include('templates/day.tpl.php');
include('templates/footer.tpl.php');

?>

In der header.tpl.php:

<html>
  <head>
    <title><?php echo $title; ?></title>
  </head>

  <body>

In der footer.tpl.php:

  </body>
</html>

Und schließlich in der day.tpl.php:

<p>Heute ist <?php echo $day_today; ?>.</p>
<p>In einem Jahr ist <?php echo $day_in_1_year; ?>.</p>
Wikibooks buchseite.svg Zurück zu Variablen | One wikibook.svg Hoch zu PHP | Wikibooks buchseite.svg Vor zu Typen und Operatoren


Websiteentwicklung: 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()[Bearbeiten]

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:

<?php

var_dump('Dschungel');
/* Ausgabe:
string(9) "Dschungel" */
?>

String[Bearbeiten]

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

<?php

$erster_string = 'Ich bin ein String';
$leerer_string = '';

?>

Strings definieren[Bearbeiten]

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.

Den Themenbereich Strings definieren vertiefen...


Einfache Anführungszeichen[Bearbeiten]

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:

<?php

'Ein String mit \', dem einfachen Anführungszeichen';

?>

Da der Backslash als Escapezeichen verwendet wird, musst du, wenn du diesen ausgeben willst, den Backslash selbst escapen (\\).

Doppelte Anführungszeichen[Bearbeiten]

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:

<?php

$variable = 'Affe';

echo 'Im Dschungel lebt ein $variable.'; // Ausgabe: Im Dschungel lebt ein $variable.
echo "Im Dschungel lebt ein $variable."; // Ausgabe: Im Dschungel lebt ein Affe.

echo "Diesen Zeilenumbruch \n siehst du nur im Quelltext der HTML-Seite (weil er kein br-Tag ist).";

echo "Man kann den Zeilenumbruch
auch direkt eingeben.";

echo 'Aber in einfachen Anführungszeichen funktioniert \n er nicht.';

?>

Es kann vorkommen, dass auf den Variablennamen noch ein Zeichen folgen kann, was PHP dem Variablennamen zurechnen würde:

<?php

$variable = 'Affe';

echo "Im Dschungel leben viele $variablen."; // Ausgabe: Im Dschungel leben viele .

?>

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:

<?php

$variable = 'Affe';

echo "Im Dschungel leben viele {$variable}n."; // Ausgabe: Im Dschungel leben viele Affen.

?>
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 (.)[Bearbeiten]

Um aus zwei Strings einen zu machen, kannst du den Verkettungsoperator (.) verwenden:

<?php

$ort = 'Dschungel';
$tier = 'Affe';

echo 'Im ' . $ort . ' lebt ein ' . $tier; // Im Dschungel lebt ein Affe
echo 'Jeder ' . $tier . ' ist ein Tier, aber nicht jedes Tier ist ein ' . $tier; /* Jeder Affe ist ein Tier,
                                                                       aber nicht jedes Tier ist ein Affe */

$tier = $ort . $tier;

echo $tier; // DschungelAffe


?>

Für die Zuweisung $variable = $variable . $string gibt es auch eine Kurzschreibweise:

<?php

$wort1 = 'Dies';
$wort2 = ' ist';
$wort3 = ' ein';
$wort4 = ' Satz';

$satz  = $wort1;
$satz .= $wort2; // ist dasselbe wie: $satz = $satz . $wort2;
$satz .= $wort3;
$satz .= $wort4;

?>

Integer[Bearbeiten]

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

Die Operatoren +, -, *, / und %[Bearbeiten]

Auf Integers kannst du die üblichen Rechenoperationen anwenden: + Addition, - Subtraktion, * Multiplikation und / Division, sowie den Modulus %, der den Rest einer Division zurückgibt.

<?php

echo 1 + 1; // 2
echo 2 * 21; // 42
echo 3 - 4; // -1
echo 10 / 2; // 5
echo 7 % 3; // 1, denn 7 geteilt durch 3 ist 2 Rest 1

$var = 1 / 2; // 0,5; $var ist jetzt vom Typ Float

$evil = 10 / 0; // ungültig; erzeugt Fehlermeldung "Warning: Division by zero"

?>

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[Bearbeiten]

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.

<?php

$a = 5;

echo $a++; // gibt 5 aus
echo $a; // gibt 6 aus
echo ++$a; // gibt 7 aus

?>
Den Themenbereich Operatoren vertiefen...


Float[Bearbeiten]

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.

<?php

$float1 = 12.5;
$float2 = 3 / 4;
$float3 = 5e3; // Exponentialschreibweise, dasselbe wie 5 mal 10 hoch 3 bzw. 5 * pow(10, 3) oder 5000

?>

Auf Floats können die gleichen Rechenoperationen wie auf Integers angewendet werden.

Boolean[Bearbeiten]

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.

<?php

$wahr = true;
$falsch = false;

$int = 15;

var_dump(is_int($int)); /* is_int prüft, ob eine Variable vom Typ Integer ist.
Ausgegeben wird: bool(true) */

$int .= 'Test'; // $int wird zum String '15Test'
var_dump(is_int($int)); // Ausgabe: bool(false)

?>

Casting[Bearbeiten]

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.

<?php

$test = '5'; // String
$zahl = (int)$test; // Casten zu Integer (5)
$bool = (bool)$test; // Casten zu Bool (true)

?>

Umfangreiche Informationen, was bei einem Casting für ein Wert angenommen wird, findest du im Referenzkapitel Variablen.

Spezialfall Booleans[Bearbeiten]

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:

false    #=> Boolean
0        #=> Integer
0.0      #=> Float
""       #=> leerer String
"0"      #=> String
array()  #=> leeres Array (Arrays werden in einem späteren Kapitel noch behandelt)
NULL     #=> also auch alle nicht gesetzten Variablen

Alle anderen Werte werden als true ausgewertet!

Wikibooks buchseite.svg Zurück zu Templating | One wikibook.svg Hoch zu PHP | Wikibooks buchseite.svg Vor zu Mit dem PHP-Handbuch arbeiten


Websiteentwicklung: PHP: 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[Bearbeiten]

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:

http://de.php.net/NAME_DER_FUNKTION

Die Funktionsbeschreibung[Bearbeiten]

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:

int strpos ( string $haystack , mixed $needle [, int $offset = 0 ] )

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[Bearbeiten]

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[Bearbeiten]



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?[Bearbeiten]

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[Bearbeiten]

Die erste Möglichkeit, ein Array zu definieren, ist das Sprachkonstrukt array:

<?php

$leeres_array = array();

$himmelsrichtungen = array('Norden', 'Osten', 'Süden', 'Westen');

?>

$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

<?php

echo '<pre>';
print_r($leeres_array);
echo '</pre>';

folgende Ausgabe erzeugen:

Array
(
)

Das Array $himmelsrichtungen sieht mit print_r so aus:

Array
(
    [0] => Norden
    [1] => Osten
    [2] => Süden
    [3] => Westen
)

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:

<?php

$kunde = array('nachname' => 'Müller', 'alter' => 42, 'email' => 'mail@example.com');

?>

führt zu folgender Struktur:

Array
(
    [nachname] => Müller
    [alter] => 42
    [email] => mail@example.com
)

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:

<?php

$arr = array(4 => 'Affe', 3 => 'Dschungel', 'Norden');

?>

erzeugt folgenden Array:

Array
(
    [4] => Affe
    [3] => Dschungel
    [5] => Norden
)

Wie du siehst, sind die Elemente in der Reihenfolge, in der du sie festlegst.

Auf Werte eines Arrays zugreifen[Bearbeiten]

Um auf einen Wert in einem Array zuzugreifen, verwenden wir eckige Klammern:

<?php

$kunde = array('nachname' => 'Müller', 'alter' => 42, 'email' => 'mail@example.com');

echo $kunde['alter']; // 42

$schluessel = 'nachname';

echo $kunde[$schluessel]; // Müller

?>

Genauso können wir auch Werte neu setzen oder neue Elemente hinzufügen:

<?php

$kunde['nachname'] = 'Mustermann'; // Element bekommt neuen Wert
$kunde['vorname'] = 'Max'; // neues Element mit Schlüssel "vorname" und Wert "Max"

?>

Bei der Zuweisung (nicht beim Auslesen) dürfen wir auch den Schlüssel weglassen, um neue Werte hinzuzufügen:

<?php

$arr[] = 'A';
$arr[] = 'B';
$arr[] = 'C';

// ist das gleiche wie

$arr = array('A', 'B', 'C');

?>

Die Schreibweise mit [] ist besonders in Schleifen hilfreich.

Mehrdimensionale Arrays[Bearbeiten]

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:

<?php

$kunde1 = array(); // nicht notwendig, aber sauberer
$kunde1['nachname'] = 'Müller';
$kunde1['alter'] = 42;

$kunde2 = array();
$kunde2['nachname'] = 'Mustermann';
$kunde2['alter'] = 21;

$kunden = array($kunde1, $kunde2);
?>

Es entsteht in $kunden folgende Struktur:

Array
(
    [0] => Array
        (
            [nachname] => Müller
            [alter] => 42
        )

    [1] => Array
        (
            [nachname] => Mustermann
            [alter] => 21
        )

)

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:

<?php

echo $kunden[0]['nachname']; // Müller
echo $kunden[1]['nachname']; // Mustermann

?>

Nützliche Funktionen im Zusammenhang mit Arrays[Bearbeiten]

  • 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[Bearbeiten]

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[Bearbeiten]

<table>
<th>
<td>Name</td>
<td>Alter</td>
</th>
<?php

// das vorige mehrdimensionale Array $kunden wird wiederverwendet

foreach ($kunden as $kunde) {
  echo '<tr>';
  echo '<td>' . $kunde['nachname'] . '</td>';
  echo '<td>' . $kunde['alter'] . '</td>';
  echo '</tr>';
}

?>

</table>

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[Bearbeiten]

Es gibt noch eine zweite Variante, die foreach-Schleife zu verwenden:

<?php

$array = array('Ort' => 'Dschungel', 'Tier' => 'Affe', 'Tätigkeit' => 'Schlafen');

foreach ($array as $key => $value) {
  echo $key . ': ' . $value;
  echo '<br />';
}

?>

Diese Schreibweise von foreach erlaubt es, auch die Schlüssel zwischenzuspeichern.

foreach und Referenzen[Bearbeiten]

$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:

<?php

$array = array(1, 3, 4, 5);

foreach ($array as &$value) {
  $value *= 2;
}
unset($value);
?>

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.


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[Bearbeiten]

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[Bearbeiten]

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?[Bearbeiten]

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[Bearbeiten]

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[Bearbeiten]

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[Bearbeiten]

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[Bearbeiten]

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[Bearbeiten]

Alle folgenden Befehle sind gefährlich:

<?php

// Nicht nachmachen!

$file = fopen($_GET['file']); // fopen: öffnet eine Datei.. oder URL

include $_GET['page'] . '.php'; // mit NUL-Byte kann auch eine Datei eingebunden werden, die nicht auf php endet

unlink($_GET['file']); // unlink: löscht eine Datei

?>

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[Bearbeiten]

<?php

// Nicht nachmachen!

$query = "SELECT username FROM users WHERE username = '". $_POST['username'] . '" AND password = '" . $_POST['password'] . "'";

?>

Wird nun vom Benutzer der (vorhandene) Benutzername "Max" und als Passwort "' OR 1 = 1" übergeben, liest sich der Query so:

SELECT username FROM users WHERE username = 'Max' AND password = '' OR 1 = 1

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[Bearbeiten]

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:

<?php

$id = (int)$_GET['id'];
$price = (float)$_POST['price'];

?>

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[Bearbeiten]

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:

<?php

$username = mysql_real_escape_string($_POST['username']); // Sinnvoll wäre hier auch noch trim
$password = mysql_real_escape_string($_POST['password']);

$query = "SELECT username FROM users WHERE username = '$username' AND password = '$password'";

?>

Wenn du den universalen Adapter PDO benutzt, kannst du die Methode quote verwenden. Mehr über PDO im entsprechenden Kapitel.

Verwendung von Prepared Statements[Bearbeiten]

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:

<?php
/**
 * @var PDO $db dies ist eine Instanz eines PHP Data Object
 */
$stmt = $db->prepare("SELECT username FROM users WHERE username = :username AND password = :password");

$stmt->bindParam(':username', $_POST['username']);
$stmt->bindParam(':password', $_POST['password']);

$stmt->execute();

?>
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)[Bearbeiten]

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.

<?php

echo htmlspecialchars($_POST['text']);

?>

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)[Bearbeiten]

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[Bearbeiten]

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[Bearbeiten]

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[Bearbeiten]

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



Websiteentwicklung: PHP: Praktische Einführung: Benutzereingaben verwenden

Übergabe von Parametern per GET[Bearbeiten]

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:

exchange.php?from=dollar-us&to=euro&amount=10

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[Bearbeiten]

show_get.php:

<html>
  <head>
    <title>GET-Beispiel</title>
  </head>

  <body>

  <p>Du möchtest <?php echo (float)$_GET['amount']; ?> <?php echo htmlspecialchars($_GET['from']); ?> in <?php echo htmlspecialchars($_GET['to']); ?> umwandeln.</p>

  <p>
    <a href="show_get.php?from=dollar-us&amp;to=euro&amp;amount=10">10 US-Dollar in Euro</a><br />
    <a href="show_get.php?from=euro&amp;to=dollar-us&amp;amount=4">4 Euro in US-Dollar</a><br />
    <a href="show_get.php?from=chf&amp;to=euro&amp;amount=12.99">12,99 Schweizer Franken in Euro</a>
  </p>

  </body>

</html>
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[Bearbeiten]

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:

<html>
<head>
  <title>GET-Beispiel</title>
</head>
<body>
<?php
/* auswählbare Währungen */
$currencies = array('dollar-us' => 'US-Dollar', 'euro' => 'Euro', 'chf' => 'Schweizer Franken');

/* Nutzereingaben prüfen; wenn die Werte gültig sind, dann Info anzeigen */
if( !empty($_GET['from']) && in_array($_GET['from'], array_keys($currencies))
 && !empty($_GET['to'])   && in_array($_GET['to'],   array_keys($currencies)) )
{
?>
  <p>Du möchtest <?php echo (float)$_GET['amount']; ?> <?php echo $currencies[$_GET['from']]; ?> in <?php echo $currencies[$_GET['to']]; ?> umwandeln.</p>
<?php
}
?>

  <form method="get">
    <label>Ursprungswährung:
    <select name="from" size="1">
    <?php
    foreach ($currencies as $key => $value)
    {
      echo '<option value="' . $key . '">' . $value . '</option>';
    }
    ?>
    </select></label><br />

    <label>Zielwährung:
    <select name="to" size="1">
    <?php
    foreach ($currencies as $key => $value)
    {
      echo '<option value="' . $key . '">' . $value . '</option>';
    }
    ?>
    </select></label><br />

    <label>Betrag:
    <input type="text" name="amount" /></label><br />

    <input type="submit" value="Umrechnen" />
  </form>

</body>
</html>

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[Bearbeiten]

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

Checkboxes[Bearbeiten]

Um Checkboxes ("Kontrollkästchen") in PHP verwenden zu können, müssen die Boxen einer Gruppe als Array importiert werden:

Früchte wählen: <br />

<input type="checkbox" name="fruits[]" value="banana">Banane <br />
<input type="checkbox" name="fruits[]" value="apple">Apfel <br />
<input type="checkbox" name="fruits[]" value="orange">Orange <br />

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.


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?[Bearbeiten]

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[Bearbeiten]

Die einfachste Verzweigung in PHP ist die if-Verzweigung:

<?php

if (true) echo 'Hallo Welt!';

?>

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

<?php

if (false) echo 'Unsichtbar!';

?>

nie eine Ausgabe sehen.

Mehrere Anweisungen[Bearbeiten]

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:

<?php

if (true) {
  echo 'Hallo';
  echo ' Welt!';
}

?>
Hinweis

Anders als in C haben Variablen in PHP innerhalb einer Kontrollstruktur den selben Gültigkeitsbereich wie außerhalb der geschweiften Klammern.

Operatoren[Bearbeiten]

Die Aussagen innerhalb der Klammern können Operatoren verwenden.

Vergleichsoperatoren[Bearbeiten]

Mit Vergleichsoperatoren können Aussagen über das Verhältnis zweier Werte zueinander getroffen werden:

<?php

$a = 3;
$b = 4;

if ($a < $b) echo $a . ' ist kleiner als ' . $b . '<br />';
if ($a > $b) echo $a . ' ist größer als ' . $b . '<br />';
if ($a == $b) echo $a . ' ist gleich ' . $b . '<br />';
if ($a != $b) echo $a . ' ist ungleich ' . $b . '<br />';

?>

Als Ausgabe erhältst du:

3 ist kleiner als 4
3 ist ungleich 4

Jetzt siehst du auch, warum es wichtig ist, das einfache Gleichheitszeichen in PHP stets als Zuweisung zu sehen. Würden wir nämlich

<?php

$a = 3;
$b = 4;

if ($a = $b) echo $a . ' ist gleich ' . $b;
?>

schreiben, ergäbe die Ausgabe

4 ist gleich 4

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:

<?php

if (5 == '5') echo 'Ich bin wahr';

if (5 === '5') echo 'Ich nicht';

?>

Eine vollständige Liste der Vergleichsoperatoren findest du im ausführlichen Kapitel Operatoren.

Logische Operatoren[Bearbeiten]

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:

<?php

if (!true) echo 'Ich bin Unsichtbar!';

?>

true wurde hier zu false, somit ist die gesamte Bedingung unwahr. Ein etwas komplexeres Beispiel:

<?php

if (!(5 <= 4)) echo 'Mich sieht man';

?>

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):

<?php

if (4 > 3 && 'text' == 'text') echo 'Damit ich zu sehen bin, muss sowohl 4 größer als 3, als auch die beiden Strings übereinstimmen.';

if (true || false) echo 'Hier muss wenigstens eine Bedingung wahr sein. Da das der Fall ist, bin ich zu sehen.';

if (true xor true) echo 'Bei xor muss exakt eine der Bedingungen wahr sein (nicht beide oder keine). Deshalb bin ich unsichtbar.';

?>

Auch diese lassen sich zu komplexeren Bedingungen zusammenfügen:

<?php

if ((4 > 3 && false) || (1 != 1 || true)) echo 'Hallo Welt!';

?>

"Hallo Welt" wird ausgegeben, da

(4 > 3 && false) || (1 != 1 || true)

ausgewertet wird zu

(false) || (true)

else und elseif[Bearbeiten]

Mit else kannst du Anweisungen festlegen, die nur ausgeführt werden, wenn die Bedingung nicht zutrifft:

<?php

// Entferne die Kommentarmarkierung einer der folgenden beiden Zeilen zum Testen:
// $a = true;
// $a = false;

if ($a) {
  echo '$a ist wahr';
  } else {
  echo '$a ist unwahr';
}

?>

Außerdem lässt sich mit elseif auch für diesen Fall eine weitere Bedingung stellen:

<?php

if ($a < $b) {
  echo '$a ist kleiner $b';
  } elseif ($a == $b) {
  echo '$a ist gleich $b';
  } else {
  echo '$a ist größer $b';
}

?>

switch[Bearbeiten]

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:

<?php

$number = (int)$_GET['number'];

echo "Die Zahl $number heißt ausgeschrieben: ";

if ($number == 1) {
  echo 'Eins';
} elseif ($number == 2) {
  echo 'Zwei';
} elseif ($number == 3) {
  echo 'Drei';
} elseif ($number == 4) {
  echo 'Vier';
} elseif ($number == 5) {
  echo 'Fünf';
} else {
  echo 'Ungültige Zahl!';
}

?>

In dieser if-Abfrage wird ein und dieselbe Variable mit zahlreichen Werten verglichen. Für diese Aufgabe gibt es eine spezielle Kontrollstruktur: switch.

$number = (int)$_GET['number'];

echo "Die Zahl $number heißt ausgeschrieben: ";

switch ($number) {
  case 1:
    echo 'Eins';
    break;
  case 2:
    echo 'Zwei';
    break;
  case 3:
    echo 'Drei';
    break;
  case 4:
    echo 'Vier';
    break;
  case 5:
    echo 'Fünf';
    break;
  default:
    echo 'Ungültige Zahl!';
}

Sehen wir uns die einzelnen Bestandteile der Anweisung einmal genauer an.

switch[Bearbeiten]

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[Bearbeiten]

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:

<?php

switch ($number) {
  case 2:
  case 3:
  case 5:
    echo 'Die Zahl ist eine Primzahl.';
    break;

  case 1:
  case 4:
    echo 'Die Zahl ist keine Primzahl.';
    break;
  default:
    echo 'Ungültiger Wert';
}

?>

Dieses Beispiel funktioniert wie eine Oder-Verknüpfung (||) der Fälle.

break[Bearbeiten]

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:

<?php

// obiges Beispiel ohne break

switch ($number) {
  case 2:
  case 3:
  case 5:
    echo 'Die Zahl ist eine Primzahl.';

  case 1:
  case 4:
    echo 'Die Zahl ist keine Primzahl.';

  default:
    echo 'Ungültiger Wert';
}

?>

Bei $number = 10 ist noch alles in Ordnung:

Ungültiger Wert

Mit $number = 5 zeigt sich allerdings das Problem:

Die Zahl ist eine Primzahl.Die Zahl ist keine Primzahl.Ungültiger Wert

Wie bereits beschrieben: Alle Anweisungen nach case werden ausgeführt. Da kein break erfolgt, geschieht dies mit allen drei echos.

default[Bearbeiten]

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

Trinitätsoperator[Bearbeiten]

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[Bearbeiten]

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:

<?php

$page = (isset($_GET['page'])) ? $_GET['page'] : 'index';

?>

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:

<?php

if (isset($_GET['page'])) {
  $page = $_GET['page'];
} else {
  $page = 'index';
}

?>
Den Themenbereich Kontrollstrukturen vertiefen...


Praktische Anwendung[Bearbeiten]

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.

<?php
/* Vorbelegung der Variable $page */
$page = !empty($_GET['page']) ? trim($_GET['page']) : 'index';

/* erlaubte Seiten */
$pages = array('index', 'review', 'impressum');

/* wenn die angeforderte Seite nicht im Array aufgelistet ist, wird die Seite 404 aufgerufen */
if(!in_array($page, $pages)) {
  $page = '404';
}

/* Möglicherweise gibt es noch weitere Logik für diese Seite */
$logic = 'logic/' . $page . '.php';
if (file_exists($logic))
{
  include($logic);
}

/* Ansicht einbinden */
include('templates/header.tpl.php');
include('templates/' . $page . '.tpl.php');
include('templates/footer.tpl.php');

?>

Ausblick[Bearbeiten]

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.


Websiteentwicklung: PHP: Praktische Einführung: Datenbanken

PDO (PHP-Database-Object)

PDO[Bearbeiten]

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

  1. Verbindung aufbauen
  2. query
  3. fetch


Websiteentwicklung: PHP: Praktische Einführung: Schleifen

Nuvola apps important.svg ACHTUNG: Dieses Buch oder Kapitel bedarf dringend einer Überarbeitung oder Erweiterung. Wenn du Lust hast, beteilige dich an der Verbesserung!


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[Bearbeiten]

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.

$i = 1;
while($i < 4)
{
  echo $i; # => aktuellen Wert von $i ausgeben
  $i++;    # => $i wird um eins erhöht
}
# Die Ausgabe wäre: 123

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[Bearbeiten]

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.

$i = 1;
do
{
  echo $i; # => aktuellen Wert von $i ausgeben
  $i++;    # => $i wird um eins erhöht
}
while($i < 4);
# Die Ausgabe wäre auch hier: 123

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[Bearbeiten]

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

for[Bearbeiten]

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.
$personen = array('Anna', 'Berta', 'Chris');

for($i = 0; $i < count($personen); $i++)
{
  echo $personen[$i]." ";
}
# Die Ausgabe wäre in diesem Fall: "Anna Berta Chris "

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[Bearbeiten]

break[Bearbeiten]

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

$i = 1;
while($i < 10)
{
  echo $i; # => aktuellen Wert von $i ausgeben
    if($i === 5){
      break;
    }
  $i++;    # => $i wird um eins erhöht
}
# Die Ausgabe wäre: 12345

continue[Bearbeiten]

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

<?php
while (list($key, $value) = each($arr)) {
    if (!($key % 2)) { // ignoriere ungerade Werte
        continue;
    }
    mach_etwas_ungerade($value);
}


Websiteentwicklung: PHP: Vorwort

Vorwort[Bearbeiten]

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.



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[Bearbeiten]

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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[Bearbeiten]

  1. PHP hat bislang keinen Anwendungs-Server – Das heißt, alle Variablen müssen bei jedem Aufruf wieder neu geladen bzw. berechnet werden.
  2. 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.
  3. 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.
  4. 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.
  5. PHP hat im Gegensatz zu anderen Skriptsprachen keine Möglichkeiten der Programmierung von Threads.

Unterschiede der verschiedenen Formen PHPs[Bearbeiten]

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[Bearbeiten]

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[Bearbeiten]

Ü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[Bearbeiten]

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.



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[Bearbeiten]

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[Bearbeiten]

Voraussetzungen für diese Anleitung[Bearbeiten]

  • 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[Bearbeiten]

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[Bearbeiten]

Hier ist Deine Mithilfe erforderlich!


Fahren sie nun mit Anpassen der Apache-Konfiguration fort.

UNIX-artige Systeme[Bearbeiten]

Voraussetzungen[Bearbeiten]

  • 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[Bearbeiten]

Debian und Derivate[Bearbeiten]

Debian und davon abhängende Distributionen können PHP mit apt installieren. Dafür tippt man einfach in einer beliebigen Shell

# apt-get install php4

bzw.

# apt-get install php5

Abhängigkeiten werden automatisch geladen und installiert.

Gentoo[Bearbeiten]

Nachdem sie ihren portage tree aktualisiert haben, schauen sie, was portage alles installieren möchte:

# emerge -pv dev-lang/php

Wie sie sehen, haben sie mit Gentoo fast die selben 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:

# USE="apache2 [weitere Optionen]" emerge dev-lang/php
# USE="cgi [weitere Optionen]" emerge dev-lang/php
# USE="cli [weitere Optionen]" emerge dev-lang/php

Fahren sie nun mit Anpassen der Apache-Konfiguration fort.

SuSE/openSuSE[Bearbeiten]

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[Bearbeiten]

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:

  $ cd /opt/src
  $ tar -xjf php-x.x.x-tar.bz2
  $ cd php-x.x.x
  $ cat README

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:

  $ ./configure --help

Sollte die Ausgabe zu lang für ihren Bildschirm sein, können sie mit einer Pipe und einen Pager arbeiten:

  $ ./configure --help | less

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[Bearbeiten]

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:

  $ ./configure \
  --prefix=/opt/php/cgi \
  --disable-short-tags \
  --enable-discard-path \
  --enable-force-cgi-redirect \
  --enable-memory-limit \
  --with-bz2 \
  --with-config-file-path=/etc \
  --with-config-file-scan-dir=/opt/htdocs \
  --with-openssl \
  --with-zend-vm=GOTO \
  --with-zlib

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.

Achten sie auf Fehlermeldungen!

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:

  configure: error: Cannot find OpenSSL's <evp.h>

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.

Wurde configure explizit angewiesen eine Erweiterung zu nutzen, reicht es bereits aus, die entsprechende Option --with-[NAME] oder --enable-[NAME] zu entfernen. Wurde configure nicht explizit angewiesen, müssen sie die entsprechende Erweiterung durch --without-[NAME] oder --disable-[NAME] ausschließen.

Kompilieren sie nun die Quellen und schließen sie die Installation ab:

  $ make
  $ make install

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:

  $ ./configure
  --prefix=/opt/php/cli \
  --disable-cgi \
  [weitere Optionen]
  
  $ make
  $ make install

Modul für den Apachen 1.x erstellen[Bearbeiten]

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:

  $ tar -xzf apache_1.3.x.tar.gz
  $ cd apache_1.3.x
  $ ./configure
  
  $ cd ..
  $ tar -xjf php-5.x.x.tar.bz2
  $ cd php-5.x.x
  $ ./configure \
  --with-apache=/pfad/zu/den/Sourcen/apaches \
  --enable-safe-mode \
  --with-mysql \
  --with-openssl \
  --with-zend-vm=GOTO \
  --with-zlib
  $ make
  $ make install
  
  $ cd ../apache_1.3.x
  $ ./configure \
  --prefix=/opt/test \
  --activate-module=src/modules/php5/libphp5.a \
  [weitere Optionen]
  $ make
  $ make install

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.

  $ ./configure \
  --with-apxs=/pfad/zu/apache/bin/apxs \
  --with-config-file-path=/etc \
  --with-config-file-scan-dir=/opt/htdocs \
  --enable-safe-mode \
  --with-mysql \
  --with-openssl \
  --with-zend-vm=GOTO \
  --with-zlib
  $ make
  $ make install

Das so erstellte Modul wird Direktiven der php.ini stets beachten.

Modul für den Apachen 2.x erstellen[Bearbeiten]

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:

 $ ./configure \
 --with-apxs2=/pfad/zu/apache2/bin/apxs \
 --with-config-file-path=/etc \
 --with-config-file-scan-dir=/opt/htdocs \
 --enable-safe-mode \
 --with-mysql \
 --with-openssl \
 --with-zend-vm=GOTO \
 --with-zlib
 $ make
 $ make install

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[Bearbeiten]

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:

$ ./configure \
--prefix=/opt/php \
--disable-all \
--disable-cgi
$ make
$ make install

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:

$ cd ext/ && ls

Weitere Erweiterungen können von pecl.php.net oder anderen Anbietern bezogen werden. Die Vorgehensweise ist dabei stets die selbe.

Erstellen sie nun ihr erstes PHP-Modul für Perl-kompatible Reguläre Ausdrücke:

$ cd pcre/
$ /opt/php/bin/phpize

Dabei wird ihnen folgende Fehlermeldung ausgegeben:

Cannot find config.m4.
Make sure that you run '/opt/php/bin/phpize' in the top level source directory of the module

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:

$ cp config0.m4 config.m4
$ /opt/php/bin/phpize
$ ./configure --with-php-config=/opt/php/bin/php-config
$ make
$ make install
$ cd ..

Nehmen Sie sich nun eine andere Erweiterung als zusammenhängendes Beispiel vor:

$ cd posix/
$ /opt/php/bin/phpize
$ ./configure --with-php-config=/opt/php/bin/php-config
$ make
$ make install

Tipps und Tricks[Bearbeiten]

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:

CFLAGS="-O3 -march=athlon-xp -fomit-frame-pointer -pipe" ./configure ...

Ober bestimmen Sie breits beim Kompilieren, wo Sie Ihre Include-Dateien abgelegt haben oder Ihr Verzeichnis für die PHP-Module angelegt werden soll:

INCLUDE_PATH="/opt/php/inc:/home/eddi/inc:." ./configure ...
EXTENSION_DIR="/opt/php/modules" ./configure ...

Vereinfachungen

Legen Sie sich ein wiederverwendbare Konfigurationsdatei an und führen Sie diese von Version zu Version aus:

$ source ../mein-conifg-fuer-php.conf

Eine Beispielkonfigurationsdatei:

EXTENSION_DIR="/opt/php/modules" \
INCLUDE_PATH="/opt/php/inc:/home/eddi/inc:." \
CFLAGS="-O3 -march=athlon-xp -fomit-frame-pointer -pipe" \
./configure \
--prefix=/opt/php/513 \
--disable-all \
--disable-cgi \
--disable-short-tags \
--enable-memory-limit \
--enable-pcntl \
--enable-posix \
--enable-sigchild \
--enable-sysvsem \
--enable-sysvshm \
--with-bz2 \
--with-config-file-path=/opt/conf \
--with-openssl \
--with-zend-vm=GOTO \
--with-zlib

Anpassen der Apache-Konfiguration[Bearbeiten]

Konfiguration für CGI[Bearbeiten]

Nehmen sie in die Apache-Konfigurationsdateien (httpd.conf/.htaccess) folgende Direktiven auf:

ScriptAlias /wikiphp/                      /pfad/zum/Verzeichnis/des/CGI-Programm/
Action      application/x-httpd-php        /wikiphp/php
Action      application/x-httpd-php-source /wikiphp/php

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:

ScriptAlias /wikiphp/                      "C:/php/"
Action      application/x-httpd-php        "/wikiphp/php.exe"
Action      application/x-httpd-php-source "/wikiphp/php.exe"

Konfiguration für mod_php[Bearbeiten]

Nehmen sie folgende Zeilen in ihre httpd.conf auf, wenn diese noch nicht vorhanden sind:

LoadModule php5_module modules/libphp5.so

Für Windows notieren sie bitte eine der folgenden Zeilen (Je nach Version Apaches und PHP):

LoadModule php5_module "C:/php/php5apache2.dll"
LoadModule php5_module "C:/php/php5apache.dll"

Skripte durch Endungen erkennen[Bearbeiten]

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:

AddType application/x-httpd-php        phtml php php5
AddType application/x-httpd-php-source phps

Darüber hinaus können sie Verzeichnisweit (.htaccess) mit der Direktive AddType arbeiten:

AddType application/x-httpd-php        php
AddType application/x-httpd-php-source phps



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[Bearbeiten]

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[Bearbeiten]

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.


Websiteentwicklung: PHP: Konfiguration

Grundlegendes[Bearbeiten]

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.

Erläuterung der Konstanten
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[Bearbeiten]

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:

<?php
phpinfo(4); # Hauptdirektiven
phpinfo(8); # Direktiven und Angaben eingebundener Erweiterungen
?>

Hinweis: Das PHP-Komandozeilenprogramm (CLI) parst nur Dateien mit Namen php-cli.ini.


Syntax[Bearbeiten]

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[Bearbeiten]

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:

<?php phpinfo(1); ?>

Eine mögliche Ausgabe könnte so aussehen:

PHP Version 5.1.3
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.*
This program makes use of the Zend Scripting Language Engine:
Zend Engine v2.1.0, Copyright (c) 1998-2006 Zend Technologies

Hinweis: Die Konfiguration der Direktive expose_php lässt sich ausschließlich in der php.ini vornehmen.


Konfiguration unter Apache[Bearbeiten]

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:

<?php echo php_sapi_name(); ?>

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[Bearbeiten]

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:

<VirtualHost 127.0.0.1:80>
        ServerName      localhost
        ServerAlias     mein.server
        DocumentRoot    /var/www/default

        <Directory /var/www/default>
                AllowOverride   All
                php_value       include_path        ".:/var/www/inc:/var/www/default/inc"
                php_admin_value memory_limit         2M
                php_admin_value open_basedir         /var/www/default
                php_admin_value post_max_size        100K
                php_admin_flag  safe_mode            On
                php_admin_value upload_max_filesize  0
                php_admin_value upload_tmp_dir       /var/www/uploads
        </Directory>
        <Directory /var/www/default/html>
                php_admin_flag  file_uploads         Off
        </Directory>
        <Directory /var/www/default/upload>
                php_admin_value doc_root             /var/www/default/upload
                php_admin_flag  file_uploads         On
                php_admin_value include_path        "."
                php_admin_value post_max_size        14M
                php_admin_value upload_max_filesize  12M
        </Directory>

        # Andere Angaben
</VirtualHost>

PHP als CGI[Bearbeiten]

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:

#!/bin/sh
if [ -e /pfad/zu/php ]
	then
	scandir=`/bin/dirname ${PATH_TRANSLATED}`;
	default='/pfad/zur/default_ini/php.ini';
	cgiprog='/pfad/zu/php -c'

	if [ -e "$scandir/php.ini" ]
		then	$cgiprog $scandir;
		else	$cgiprog $default;
	fi

	else	exit 1;
fi
exit $?;

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:

ScriptAlias /wikiphp/                      /pfad/zum/php/verzeichnis/
Action      application/x-httpd-php        /wikiphp/startphp.sh
Action      application/x-httpd-php-source /wikiphp/startphp.sh

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:

#!/bin/sh
if [ -e /pfad/zu/php ]
	then
	scanini="/pfad/zur/kunden/${SERVER_NAME}.ini";
	default='/pfad/zur/default_ini/php.ini';
	cgiprog='/pfad/zu/php -c'

	if [ -e $scanini ]
		then	$cgiprog $scanini;
		else	$cgiprog $default;
	fi

	else	exit 1;
fi
exit $?;

Die Konfigurationsdatei für den Virtualhost localhost heißt also localhost.ini.

Konfiguration innerhalb von Skripten[Bearbeiten]

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:

<?php
header('Content-Type: application/xhtml+xml; charset=iso-8859-15',true);
?>
<?php
ini_set('default_mimetype','application/xhtml+xml');
ini_set('default_charset', 'iso-8859-15');
?>

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:

<?php
ini_set('display_errors',     false);   # boolean
ini_set('log_errors_max_len', 128);     # integer
ini_set('error_log',         'syslog'); # string
?>

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[Bearbeiten]

in Bearbeitung!

Der abgesicherte Modus[Bearbeiten]

in Bearbeitung!

Dateien hochladen[Bearbeiten]

in Bearbeitung!

Datenkompression für Webserver[Bearbeiten]

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:

zlib.output_compression      =1
zlib.output_compression_level=9

oder Konfiguration am Anfang eines jeden Skripts:

ini_set('zlib.output_compression',1);
ini_set('zlib.output_compression_level',9);

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[Bearbeiten]

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:

Options +MultiViews

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:

application/x-httpd-php xhtm xhtml

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:

HTTP/1.1 200 OK
Date: Sun, 14 May 2006 06:36:26 GMT
Server: Apache/1.3.35 (Unix) PHP/5.1.4
Content-Location: test.php
TCN: choice
Vary: negotiate,accept
Connection: close
X-Powered-By: PHP/5.1.4
Transfer-Encoding: chunked
Content-Type: text/plain;charset=iso-8859-1

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[Bearbeiten]

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:

<Files meinwiki>
       ForceType       application/x-httpd-php
       AcceptPathInfo  On
</Files>

Diese Konfiguration wird den Apache veranlassen die Datei meinwiki wie ein PHP-Skript zu behandeln. Erstellen Sie nun das Skript meinwiki:

<?php

$a = array(
  'application/xhtml+xml' => array('xhtm', 'xhtml'),
  'application/xml' => array('xml'),
  'text/plain' => array('txt', 'asc'),
  'text/html' => array('htm', 'html', 'php', 'phtml'),
);

$pfad = '.'. str_replace('../', '', $_SERVER['PATH_INFO']);

if ($pfad == '.' || (is_dir($pfad) && substr($pfad, -1) != '/')) {
  $protokol = 'http'. (isset($_SERVER['HTTPS']) ? 's' : '') .'://';
  $host = $_SERVER['HTTP_HOST'];
  $pfad = str_replace('../', '', $_SERVER['REQUEST_URI']) .'/';
  header('Location: '. $protokol . $host . $pfad, TRUE, 301);
  exit;
}
elseif (is_dir($pfad)) {
  foreach ($a as $k => $v) {
    for ($i = 0; $i < count($v); $i++) {
      if (file_exists($pfad .'index.'. $v[$i])) {
        header('Content-Type: '. $k);
        if ($v[$i]{0} == 'p') {
          require($pfad .'index.'. $v[$i]);
        }
        else {
          readfile($pfad .'index.'. $v[$i]);
        }
        exit;
      }
    }
  }
}
elseif (file_exists($pfad) && substr($pfad, -1) != '/') {
  $x = pathinfo($pfad);

  foreach ($a as $k => $v) {
    if (in_array($x['extension'], $v)) {
      header('Content-Type: '. $k);
      if ($x['extension']{0} == 'p') {
        require($pfad);
      }
      else {
        readfile($pfad);
      }
      exit;
    }
  }
}

$cgi = (substr(php_sapi_name(), 0, 3) == 'cgi') ? TRUE : FALSE;

header(($cgi ? 'Status: 404' : 'HTTP/1.1 404 Not Found'), TRUE, 404);

echo '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">';
echo '<html>';
echo '<head>';
  echo '<title>404 Not Found</title>';
echo '</head>';
echo '<body>';
  echo '<h1>Not Found</h1>';
  echo '<p>The requested URI '. $_SERVER['REQUEST_URI'] .'was not found on this server.</p>';
echo '</body>';
echo '</html>';

?>

Sie können aber auch die Pfadangaben, wie mod_rewrite es tun würde, in Variablen zerlegen:

$pfad = str_replace('../', '', $_SERVER['PATH_INFO']);

list($_GET['param'], $_GET['datei'], $_GET['vname']) = explode('/', $pfad);

Dieses entspricht folgender Rewrite-Regel:

RewriteEngine On
RewriteRule   ^meinwiki/(.*)/(.*)/(.*) scriptname.php?param=$1&datei=$2&vname=$3

Somit kommen auch Nutzer des IIS in den Genuß einer Rewriteengine.


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[Bearbeiten]

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[Bearbeiten]

Eine Beispieldatei könnte so aussehen:

<?php

echo 'Hallo Welt!';

?>

Ausgabe:

Hallo Welt!

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[Bearbeiten]

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:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de" dir="ltr">
<head>
  <title>Eine PHP-Testseite</title>
</head>
<body>
  <?php echo '<p>Eingebetteter PHP-Code</p>'; ?>
</body>
</html>

Ausgabe im Browser (für den Benutzer sichtbar):

Eingebetteter PHP-Code

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[Bearbeiten]

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[Bearbeiten]

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-Type: text/html
Content-Size: 4356

Content[Bearbeiten]

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.



Websiteentwicklung: PHP: Ausgabe

Das erste "Hello World!"[Bearbeiten]

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:

<?php
echo 'Hello World!';
?>

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

Hello World

Strings (Zeichenketten)[Bearbeiten]

Betrachten wir eine Zeile des Beispiels einmal genauer:

echo 'Hello World!';

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[Bearbeiten]

Ein PHP-Befehl wird mit einem Semikolon ; beendet.

Achtung.svg

Es ist ein häufiger Anfängerfehler, das Semikolon zu vergessen.

Single-Quotes[Bearbeiten]

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

echo 'Foobar';

Double-Quotes[Bearbeiten]

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

echo "Foobar";

Zeichen "escapen"[Bearbeiten]

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 (\\).

echo 'Foo\'bar';
echo "Foo\"bar";
echo 'Foo\\bar';

PHP interpretiert eine Escape-Kette, die keine Bedeutung besitzt nicht, so dass dann ebenfalls das Escape-Zeichen mit ausgegeben wird.


Heredoc[Bearbeiten]

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

echo <<<EOD
  foo
  bar
  "foobar"
EOD;

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[Bearbeiten]

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.

echo 'foo';
print 'foo';


Übungen[Bearbeiten]

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



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[Bearbeiten]

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:

<?php
// dieses hier wird nicht beachtet,
echo 'foobar';

# dieses auch nicht
echo 'bla'; // auch dieser Teil nicht
?>

Mehrzeilige Kommentare[Bearbeiten]

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 */.

<?php
/* Dies ist ein mehrzeiliger
   Kommentar, der etwas beschreibt. */
echo 'foobar';

/* Ein mehrzeiliger Kommentar in nur einer Zeile */
echo 'bar';
?>

Auskommentieren[Bearbeiten]

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.

 <?php
 echo 'erste Zeile';
 //echo 'zweite Zeile';
 echo 'dritte Zeile';
 /* vom Autor vorläufig deaktiviert 
 echo 'foo';
 echo 'bar';
 */
 ?>

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[Bearbeiten]

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:

 <?php
/**
 * Datei mit PHPDoc-Testkommentar
 *
 * @package test
 * @author ich
 * @version 0.1
 * @copyright keins
 */ 
echo 'erste Zeile';
 ?>



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:

echo 'Dieser Text ist statisch';

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[Bearbeiten]

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[Bearbeiten]

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[Bearbeiten]

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[Bearbeiten]

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[Bearbeiten]

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[Bearbeiten]

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[Bearbeiten]

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 =.

$variable = 0; // Deklaration und Initialisierung als INTEGER (Ganzzahl)
$text = "";  // string (Zeichenkette)

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:

$wert = ($frage) ? $wahr : $falsch;

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:

if ($frage)
{
  $wert = $wahr;
}
else
{
  $wert = $falsch;
}

Das folgende Beispiel weist der Variable nur einen Standard-Wert zu, wenn sie nicht existiert, also nicht deklariert wurde.

$wert = (isset($wert)) ? $wert : "standard";

Zuweisung[Bearbeiten]

Die Zuweisung erfolgt durch den Zuweisungsoperator in Gestalt des Ist-Gleich-Zeichens (=):

$text = 'Hello World';
$eine_zahl = 42;

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:

$text1 = 'Hello World';
$text2 = $text1;

Damit erhält auch die Variable text2 die Zeichenkette "Hello World".

Dieses Zuweisung kann man auch anders lösen:

$text1 = $text2 = "Hello World";

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:

$text = 'Hello ';
$text .= 'World!';
// analog:
// $text = $text . 'World!';

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:

$text = 'Hello '.'World!';


Jetzt haben Sie gelernt, wie man Variablen zuweist. Das folgende Programm gibt die Variable aus:

$text = 'Hello World!';
echo $text;

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:

$text = 'Hello World!';
echo 'Der Computer sagt '.$text;


Innerhalb von Anführungszeichen aber werden Variablen geparst (Englisch: parsed), also vom Interpreter gegen die ihnen zugewiesenen Werte ausgetauscht:

$text = 'Hello World!';
echo "Der Computer sagt $text";

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:

$text = "'Hello World!'";
echo '"Der Computer sprach die Worte ' . $text . ' zu uns."';

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[Bearbeiten]

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.

$foo = 1;
$bar = 2;
echo $bar;  // Ausgabe "2"
$bar = &$foo;
echo $bar;  // Ausgabe "1"
$foo = 42;
echo $bar;  // Ausgabe "2"

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[Bearbeiten]

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!

define('KONSTANTE', 'WERT');
echo KONSTANTE; // Kein $ Zeichen!
echo "Diese Aussage hat einen ". KONSTANTE;

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[Bearbeiten]

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.

$varname = 'test';
$test = 'Hallo';
echo $$varname; // Ausgabe: Hallo

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:

$varname = 'test';
$dieser_test_ist_toll = 'Test Ausgabe';
echo $dieser_$varname_ist_toll; // Würde zu einem Fehler führen, weil die Variable $varname_ist_toll
                                // nicht existiert.

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.

echo $dieser_{$varname}_ist_toll; // Ausgabe: Test Ausgabe
Achtung.svg

Dynamische Variablen kommen sehr selten zum Einsatz, da sie nur in besonderen Situationen erforderlich sind.

Übungen[Bearbeiten]

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.


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.

<?php
define('MYSQL_HOST', 'localhost');
echo MYSQL_HOST; // gibt "localhost" aus.
?>

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.

<?php
error_reporting(1 | 4 | 512);
?>

Mit den Konstanten kann man diese Funktion auch wie folgt aufrufen:

<?php
error_reporting(E_ERROR | E_PARSE | E_USER_WARNING);
?>

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.

<?php
if (defined('KONSTANTE'))
 echo 'debug';
?>

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).


Websiteentwicklung: PHP: Arrays

Numerische Arrays[Bearbeiten]

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:

<?php
$namen = array('Hans', 'Anton', 'Tina', 'Max', 'Claudia');
?>

Die einzelnen Einträge werden dann über ihren Index aufgerufen:

echo $namen[2];

Ausgabe:

Tina

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[Bearbeiten]

Es ist aber auch möglich, für die einzelnen Einträge Namen zu vergeben, mit denen die Einträge angesprochen werden:

<?php
$namen = array(
	'Müller'  => 'Hans',
	'Maier'   => 'Anton',
	'Schmidt' => 'Tina',
	'Wagner'  => 'Max',
	'Reiter'  => 'Claudia',
);
?>

Um den Namen Max ausgeben zu lassen, müsste man das schreiben:

echo $namen['Wagner'];

Ausgabe:

Max

Hinzufügen von Einträgen[Bearbeiten]

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

<?php
$array[] = 'wert';
$array[] = 'anderer wert';
?>

Mehrdimensionale Arrays[Bearbeiten]

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:

<?php
$personenliste = array(
	array(
		'Name' => 'Max Gutensen',
		'Adresse' => 'Breitscheider Straße 11',
		'Ort' => 'Bremen',
		'PLZ' => 54893,
	),
	array(
		'Name' => 'Lisa Meier',
		'Adresse' => 'Lautenschlagerstraße 23b',
		'Ort' => 'Stuttgart',
		'PLZ' => 70173,
	),
);
?>

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:

<?php
echo $personenliste[1]['Adresse'];
?>

Ausgabe:

Lautenschlagerstraße 23b
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[Bearbeiten]

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

$menge_der_elemente = count($array);

Einträge durchsuchen[Bearbeiten]

Wenn man ein Array nach einem Eintrag durchsuchen will, geht das so:

<?php
if (in_array('Hans', $namen)) {
    echo "Hans war hier!";
}
?>

Wenn man den Index eines Wertes dabei zurückgeliefert haben will, geht das so:

<?php
$namen = array(
        'Müller'  => 'Hans',
        'Maier'   => 'Anton',
        'Schmidt' => 'Tina'
);

$nachname = array_search('Anton', $namen); // => Maier
?>

Sortieren der Einträge[Bearbeiten]

Man kann Arrays auch sortieren. Möchte man die Werte sortieren, geht das mit asort:

asort($namen);

Wenn man aber nach den Namen der Werte sortieren lassen will (falls welche zugeteilt wurden) benutzt man ksort.

ksort($namen);

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:

<?php

function vergleiche($a, $b)
{
    if ($a['PLZ'] == $b['PLZ']) {
        return 0;
    }
    return ($a['PLZ'] < $b['PLZ']) ? -1 : 1;
}

usort($personenliste, 'vergleiche');

?>

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[Bearbeiten]

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.

foreach($array as $aktuellerWert) {
    echo $aktuellerWert . "\r\n";
}

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:

foreach ($array as $aktuellerSchlüssel => $aktuellerWert) {
    echo $aktuellerSchlüssel . ': ' . $aktuellerWert . "<br />\r\n";
}

End[Bearbeiten]

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

$namen = array('Hans', 'Anton', 'Tina', 'Max', 'Claudia');
echo end($namen);

Ausgabe: Claudia

Arrays analysieren[Bearbeiten]

Sollte es einmal notwendig sein, ein Array, das eventuell selbst aus Arrays besteht, genauer zu untersuchen, kann die Funktion var_dump() verwendet werden:

$arr = array("ich", array("bin", "nur"), array("ein", "kleiner"), "array", array("der", "dich"), "mag");

var_dump($arr);

Dies generiert folgende Ausgabe.

array(6) {
  [0]=>
  string(3) "ich"
  [1]=>
  array(2) {
    [0]=>
    string(3) "bin"
    [1]=>
    string(3) "nur"
  }
  [2]=>
  array(2) {
    [0]=>
    string(3) "ein"
    [1]=>
    string(7) "kleiner"
  }
  [3]=>
  string(5) "array"
  [4]=>
  array(2) {
    [0]=>
    string(3) "der"
    [1]=>
    string(4) "dich"
  }
  [5]=>
  string(3) "mag"
}

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[Bearbeiten]

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:

<?php
/* ein Array um Daten zu speichern: */
$personArray = array(
	'Name' => 'Max Gutensen',
	'Adresse' => 'Breitscheider Straße 11',
	'Ort' => 'Bremen',
	'PLZ' => 54893,
);

/* caste das Array in ein Objekt */
$personObjekt = (object)$personArray;

var_dump($personArray['Adresse']);
var_dump($personObjekt->Adresse);
?>

Ausgabe:

string(24) "Breitscheider Straße 11"
string(24) "Breitscheider Straße 11"
<?php
/* ein Objekt um Daten zu speichern: */
$personObjekt = new stdClass();
$personObjekt->Name = 'Max Gutensen';
$personObjekt->Adresse = 'Breitscheider Straße 11';
$personObjekt->Ort = 'Bremen';
$personObjekt->PLZ = 54893;

/* caste das Objekt in ein Array */
$personArray = (array)$personObjekt;

var_dump($personArray['Adresse']);
var_dump($personObjekt->Adresse);
?>

Ausgabe:

string(24) "Breitscheider Straße 11"
string(24) "Breitscheider Straße 11"



Websiteentwicklung: PHP: Operatoren

Übersicht[Bearbeiten]

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[Bearbeiten]

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[Bearbeiten]

Zuerst das Rechnen mit zwei Variablen:

<?php
$zahl1 = 20;
$zahl2 = 5;
$summe     = $zahl1 + $zahl2; // Ergebnis: 25
$differenz = $zahl1 - $zahl2; // Ergebnis: 15
$produkt   = $zahl1 * $zahl2; // Ergebnis: 100
$quotient  = $zahl1 / $zahl2; // Ergebnis: 4
$rest      = $zahl1 % $zahl2; // Ergebnis: 0
?>

Beispiele: Variablen und Zahlen[Bearbeiten]

Jetzt das Rechnen mit einer Variable und einer Zahl

<?php
$zahl1 = 20;
$summe     = $zahl1 + 2; // Ergebnis: 22
$differenz = $zahl1 - 2; // Ergebnis: 18
$produkt   = $zahl1 * 2; // Ergebnis: 40
$quotient  = $zahl1 / 2; // Ergebnis: 10
$rest      = $zahl1 % 2; // Ergebnis: 0
?>

Beispiele: Zahlen[Bearbeiten]

Und schließlich das Rechnen nur mit Zahlen:

<?php
$summe     = 20 + 8; // Ergebnis: 28
$differenz = 20 - 8; // Ergebnis: 12
$produkt   = 20 * 8; // Ergebnis: 160
$quotient  = 20 / 8; // Ergebnis: 2.5
$rest      = 20 % 8; // Ergebnis: 4
?>

Zuweisungsoperatoren[Bearbeiten]

Der einfachste Zuweisungsoperator ist "=". Er weist der Variablen auf seiner linken Seite den Ausdruck auf seiner rechten Seite zu.

<?php
$a = 5;
$b = $a;
echo $b; // Ausgabe: 5
?>

Zu beachten ist, dass auf der linken Seite eine Variable stehen muss. Eine Zuweisung wie

$b = $a = 5;

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

$b = 1 + $a = 5;

ist dagegen ungültig. Eine korrekte Schreibweise wäre hingegen:

$b = 1 + ($a = 5);

Nach dieser Anweisung enthält $a den Wert 5 und $b den Wert 6.

Neben dem einfachen Zuweisungsoperator gibt es einige "kombinierte Operatoren":

<?php
$a = 5;
$b = 20;

$b += $a;  // Gleichbedeutend mit $b = $b + $a;  Ergebnis: 25
$b -= $a;  // Gleichbedeutend mit $b = $b - $a;  Ergebnis: 15
$b *= $a;  // Gleichbedeutend mit $b = $b * $a;  Ergebnis: 100
$b /= $a;  // Gleichbedeutend mit $b = $b / $a;  Ergebnis: 4
$b %= $a;  // Gleichbedeutend mit $b = $b % $a;  Ergebnis: 0
$b .= $a;  // Gleichbedeutend mit $b = $b . $a;  Ergebnis: 205
$b &= $a;  // Gleichbedeutend mit $b = $b & $a;  Ergebnis: 4
$b |= $a;  // Gleichbedeutend mit $b = $b | $a;  Ergebnis: 21
$b ^= $a;  // Gleichbedeutend mit $b = $b ^ $a;  Ergebnis: 17
$b <<= $a; // Gleichbedeutend mit $b = $b << $a; Ergebnis: 640
$b >>= $a; // Gleichbedeutend mit $b = $b >> $a; Ergebnis: 0
?>

Inkrement- und Dekrementoperatoren[Bearbeiten]

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
$a = 25;
echo ++$a; // Ausgabe: 26, $a == 26
echo $a++; // Ausgabe: 26, $a == 27
echo $a--; // Ausgabe: 27, $a == 26
echo --$a; // Ausgabe: 25, $a == 25

Bit-Operatoren[Bearbeiten]

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.

<?php
$a = 45;      //               00101101
$b = 205;     //               11001101
$c = $a & $b; // Ergebnis: 13; 00001101
?>

Der Bit-Operator | (oder) setzt alle Bits, die in $a oder $b gesetzt sind.

<?php
$a = 45;      //                00101101
$b = 205;     //                11001101
$c = $a | $b; // Ergebnis: 237; 11101101
?>

Der Bit-Operator ^ (exklusiv oder) setzt alle Bits, die in $a oder $b, aber nicht in beiden gesetzt sind.

<?php
$a = 45;      //                00101101
$b = 205;     //                11001101
$c = $a ^ $b; // Ergebnis: 224; 11100000
?>

Der Bit-Operator ~ (nicht) setzt alle Bits, die nicht gesetzt sind, und löscht alle Bits, die gesetzt sind.

<?php
$a = 205; //               11001101
$b = ~$a; // Ergebnis: 50; 00110010
?>

Der Bit-Operator << (nach links verschieben) verschiebt alle Bits seines linken Operanden um die im rechten angegebene Zahl nach links.

<?php
$a = 13;      //               00001101
$b = $a << 2; // Ergebnis: 52; 00110100
?>

Der Bit-Operator >> (nach rechts verschieben) verschiebt alle Bits seines linken Operanden um die im rechten angegebene Zahl nach rechts.

<?php
$a = 13;      //              00001101
$b = $a >> 2; // Ergebnis: 3; 00000011
?>

Bit-Operatoren als Flags[Bearbeiten]

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

Beispiel
<?php

$verfassen    = 1; // 00000001
$editieren    = 2; // 00000010
$freischalten = 4; // 00000100
$loeschen     = 8; // 00001000

$gast_rechte = $verfassen; // 00000001
$benutzer_rechte = $gast_rechte | $editieren; // 00000011
$moderator_rechte = $benutzer_rechte | $freischalten; // 00000111
$admin_rechte = $moderator_rechte | $loeschen; // 00001111

echo 'Ein Gast darf Beiträge verfassen: ';
echo $gast_rechte & $verfassen;

echo '<br />';

echo 'Ein Moderator darf Beiträge löschen: ';
echo $moderator_rechte & $loeschen;
?>
Ausgabe
Ein Gast darf Beiträge verfassen: 1
Ein Moderator darf Beiträge löschen: 0

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[Bearbeiten]

Die Vergleichs-Operatoren geben eine Booleanschen Ausdruck (true oder false) zurück. Sie lassen sich auf jeden Ausdruck anwenden.

Operator Bedeutung Ergebniss
$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[Bearbeiten]

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[Bearbeiten]

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
$array1 = array('Schluessel1' => 'Wert1');
$array2 = array('Schluessel2' => 'Wert2');
$array3 = $array1 + $array2;
//$array3 = array('Schluessel1' => 'Wert1', 'Schluessel2' => 'Wert2');

Die Arrays werden zu einem Array zusammengefasst

$array1 = array('Schluessel' => 'Wert1');
$array2 = array('Schluessel' => 'Wert2');
$array3 = $array1 + $array2;
//$array3 = array('Schluessel' => 'Wert1');

Der unterschiedlich belegte Schlüssel "Schluessel" erhält den Wert des zuerst angegebenen Arrays $array1

Der Zeichenketten-Operator .[Bearbeiten]

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

Beispiele
$a = "Ich bin eine";
$b = "zusammengesetzte Zeichenkette";
echo $a." ".$b.chr(10); // chr(10) ist ein Zeilenumbruch
$a = 20;
$b = 5;
echo $a.$b.chr(10);
$a = "Zeichenkette ";
$b = 5;
echo $a.$b;
Ausgabe
Ich bin eine zusammengesetzte Zeichenkette
205
Zeichenkette 5

Der Auswahl-Operator ?:[Bearbeiten]

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

Syntax
$ergebnis = (boolwert) ? bei_true : bei_false ;

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

Beispiel
echo "Die größere Zahl wird zuerst ausgeben:\n";
$a = 6;
$b = 30;
echo "\$a == $a und \$b == $b\n";
echo ($a > $b ? $a.chr(10).$b : $b.chr(10).$a).chr(10);
$a = 41;
$b = 22;
echo "\$a == $a und \$b == $b\n";
echo ($a > $b ? $a.chr(10).$b : $b.chr(10).$a).chr(10);
Ausgabe
Die größere Zahl wird zuerst ausgeben:
$a == 6 und $b == 30
30
6
$a == 41 und $b == 22
41
22

Der Fehler-Kontroll-Operator @[Bearbeiten]

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[Bearbeiten]

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.

$dz=@mysql_connect('localhost','Benutzer','Passwort') or
    die('Es konnte keine Verbindung zum Datenbankserver hergestellt werden!');


Websiteentwicklung: PHP: Kontrollstrukturen

Einfache Abfragen[Bearbeiten]

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:

<?php
if (Bedingung) {
    // Anweisung
}
?>

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:

<?php
if ('Hans' == $benutzername) {
    echo 'Du bist Hans';
}
?>

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:

<?php
// ACHTUNG! Falscher Code!
if ($benutzername = 'Hans') {
    echo 'Du bist Hans';
}
?>

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.

if ($a == $b) echo $a;

Else und Elseif[Bearbeiten]

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:

<?php
if (Bedingung) {
    // Anweisung
} 
else {
    // Anweisung
}
?>

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:

<?php
if     (Bedingung) {
    // Anweisung
} 
elseif (Bedingung) {
    // Anweisung
}
?>

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:

<?php
if     ('Hans' == $benutzername) {
    echo 'du bist Hans';
} 
elseif ('Anton' == $benutzername) {
    echo 'Du bist Anton';
} 
else {
    echo 'Dich kenne ich nicht';
}
?>
Alternative Schreibweise[Bearbeiten]

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.

if ($a == $b) :
  // Tue irgendwas sinnvolles
endif;

Mit elseif und else wird ebenso umgegangen

if ($a == $b) :
  // Tue was
elseif ($a < $b) :
  // Tue etwas anderes
else :
  // Tue sonstige Sachen
endif;

Der Vorteil liegt bei komplexen Strukturen, wo es teilweise schwer fällt herauszufinden, wozu die geschweifte Klammer am Ende einer Anweisung gehören kann.

if ($a == $b) :
  foreach ($a as $foo) :
    // mach was
  endforeach;
endif;
Trinäre Zuweisung[Bearbeiten]

Eine Besonderheit bildet eine Kurzschreibweise für Abfragen, die ohne elseif auskommen und für if und else jeweils nur eine Rückgabe besitzen.

$foo = $bar ? $wennwahr : $wennfalsch;

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.

$foo = $foo ? $foo : $standard;
// Gleichbedeutend mit
if (!$foo) $foo = $standard;


Websiteentwicklung: PHP: Switch-Abfrage

Die switch-Funktion[Bearbeiten]

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:

<?php
switch($var)
 {
   case "1": echo "Die Variable ist '1'";
             break;
   case "k": echo "Die Variable ist 'k'";
             break;
   default:  echo "Die Variable ist weder '1' noch 'k'";
 }
?>

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[Bearbeiten]

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:

switch($buchstabe) {
   case "a": //Durchfall erwünscht
   case "e":
   case "i":
   case "o":
   case "u":
      echo "Der Buchstabe ist ein Selbstlaut";
      break;
   default:
      echo "Der Buchstabe ist kein Selbstlaut";
}

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[Bearbeiten]

Ebenfalls ist wieder eine Alternative Syntax möglich.

switch ($var):
  case 'a':
    //tue etwas
  break;
endswitch;



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[Bearbeiten]

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:

 <?php
 $zahl = 0; // While-Schleife beginnt mit 0
 while ($zahl != 100) {
     echo $zahl . ', ';
     $zahl++;
 }
 ?>

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[Bearbeiten]

Syntax einer Do-While-Schleife:

 do {
     ausführungsblock
 } while (bedingung);

Hier ein Beispiel für eine Do-While-Schleife:

 <?php
 $zahl = 0;
 do {
     echo $zahl . ', ';
     $zahl++;
 } while ($zahl != 101); 
 ?>

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[Bearbeiten]

Neben While-Schleifen gibt es auch For-Schleifen. Diese sind ähnlich aufgebaut.

  for(Initialisierung; Bedingung; Aktualisierung) {
    Befehle
  }

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

 <?php
 for ($zahl = 0; $zahl < 100; $zahl++) {
     echo $zahl . ', ';
 }
 ?>

Auch diese Schleife gibt die Zahlen 0 bis 99 zurück.

Foreach-Schleifen[Bearbeiten]

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

 <?php
 $my_array = array(
     'wert1' => 'PHP',
     'wert2' => 'ASP',
 );
 foreach($my_array as $key => $value) {
     echo $key.' --> '.$value.'<br />';
 }
 ?>

Ausgabe:

   wert1 --> PHP
   wert2 --> ASP

Verwendung der verschiedenen Typen[Bearbeiten]

(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:

  <?php
    $array = array("foo" => "bar", "some" => "thing"); 

    foreach($array as $key => $value)
      echo $key." -> ".$value."\n"; 

    while(list($key, $value) = each($array))
      echo $key." -> ".$value."\n";
  ?>

Beides ergibt das selbe Ergebnis:

foo -> bar some -> thing

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.


Websiteentwicklung: PHP: Funktionen

Standardfunktionen[Bearbeiten]

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:

name_der_funktion(parameter1, parameter2, parameter3, ...);

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:

<?php
name_der_funktion(parameter1,parameter2);
name_der_funktion(parameter1, parameter2);
name_der_funktion ( parameter1, parameter2 ) ;
name_der_funktion      (      parameter1        ,    parameter2
)                   ;
name_der_funktion
(
    parameter1        ,
    parameter2
)         ;
?>

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[Bearbeiten]

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:

function name_der_eigenen_funktion(parameter1, parameter2, parameter3, ...){
      code, der von der Funktion ausgeführt werden soll}

Danach kann man diese Funktion wie jede Standardfunktion von PHP nutzen.

Beispiel:

<?php
function meinname($meinname){
  echo "Mein Name ist " . $meinname . " und ich bin in der Wikipedia zu Hause! <br />";
}

meinname("Der Wikipediander");
meinname("Die Wikipedianderin");
?>

Das Ergebnis:

Mein Name ist Der Wikipediander und ich bin in der Wikipedia zu Hause!
Mein Name ist Die Wikipedianderin und ich bin in der Wikipedia zu Hause!

Vorteil: Man braucht einen Codeschnipsel nur einmal erstellen, und kann ihn so oft man möchte benutzen.

Mehrere Parameter[Bearbeiten]

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

<?php
function meinname($meinname, $alter){
  echo "Mein Name ist " . $meinname . ", bin " . $alter . " Jahre alt und ich bin in der Wikipedia zu Hause! <br />";
}

meinname("Der Wikipediander","20");
meinname("Die Wikipedianderin","20");
?>

Ergebnis:

Mein Name ist Der Wikipediander, bin 20 Jahre alt und ich bin in der Wikipedia zu Hause!
Mein Name ist Die Wikipedianderin, bin 20 Jahre alt und ich bin in der Wikipedia zu Hause!

Eine unbekannte Zahl an Parametern[Bearbeiten]

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:

<?php
function bloodygary_foo(){
  $i = func_num_args(); // Die Anzahl der Variablen bekommen
  if($i<2)
    return "Es wurden zu wenige Parameter übergeben";
  if(func_get_arg(2)=="blubb") // Zugriff auf die einzelnen übergebenen Parameter (0 .. ?)
    return "Es wurde als 3. Parameter blubb übergeben";
  return "was auch immer";
}
?>

Anwendung des Beispiels

echo bloodygary_foo();
>> "Es wurden zu wenige Parameter übergeben"
echo bloodygary_foo("bli","bla","blubb");
>> "Es wurde als 3. Parameter blubb übergeben";
echo bloodygary_foo("irgend","was","völlig","anderes",1,23,1,31);
>> "was auch immer";

Sicherlich ist das nicht das beste Beispiel, aber zeigt dennoch etwas, das an dieser Stelle erwähnt werden sollte.

statische Variablen[Bearbeiten]

function test_static()
{
   static $a =0; //Definierung der Variable $a als statisch
   
   return $a++; //$a um eins erhöhen und zurückgeben
}

for($i=0;$i<10;$i++)
   echo test_static()."<br>";

echo $a; //Die Variable kann von außerhalb nicht ausgelesen werden!

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[Bearbeiten]

$a=0; //Definierung der Variable $a

function test_static()
{
   global $a; //Die globale Variable $a wird der Funktion zugänglich gemacht
   
   return $a++; //$a um eins erhöhen und zurückgeben
}

for($i=0;$i<=10;$i++)
   echo test_static()."<br>";

echo $a; //Die Variable kann von außerhalb ausgelesen und verändert werden!

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[Bearbeiten]

Closures sind anonyme Funktionen. Das heißt sie haben keinen Funktionsnamen.

$rechne = function($a, $b) {
    return $a + $b;
};
$rechne(3, 7); // => 10

Closures werden durch eine Variable angesprochen. Man benutzt sie hauptsächlich für "Callback"-Funktionen.


Websiteentwicklung: PHP: Include

include(), require(), include_once(), require_once()[Bearbeiten]

include()[Bearbeiten]

Mittels include() kann man Inhalte anderer Dateien an der Stelle einfügen, an der der Befehl steht.

<?php
    ...    // PHP-Code
    include 'header.inc.php';    // wird "header.inc.php" nicht gefunden, wird ein "Warning" ausgegeben
    ...    // weiterer PHP-Code
?>

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()[Bearbeiten]

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.

<?php
    ...    // einiger PHP-Code
    require 'config.inc.php';    // wird "config.inc.php" nicht gefunden, wird ein "Fatal error" ausgegeben
    ...    // weiterer PHP-Code
?>

Innerhalb einer eingebundenen Datei können natürlich weitere include() / require() Befehle enthalten sein.

include_once() und require_once()[Bearbeiten]

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().

<?php
    ...    // einiger PHP-Code
    require_once 'config.inc.php';
    ...    // weiterer PHP-Code
    require_once 'config.inc.php';    // wird vom PHP-Parser ignoriert,
                                      // da die Datei bereits eingebunden wurde
    ...    // noch mehr PHP-Code
    include_once 'header.inc.php';
    ...    // noch viel mehr PHP-Code
    include_once 'header.inc.php';    // wird vom PHP-Parser ignoriert,
                                      // da die Datei bereits eingebunden wurde
?>

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.


<?php
    ...    // einiger PHP-Code
    require_once 'my_api.inc.php';
    ...    // weiterer PHP-Code
    require_once 'My_Api.inc.php';    // wird vom PHP-Parser NICHT ignoriert, da
                                      // anderer Dateiname. Unter Umständen wird
                                      // die selbe Datei hier mehrfach eingebunden.
?>

Zusätzliche Informationen im PHP-Manual


Websiteentwicklung: PHP: MySQL

Kurze Einführung in MySQL[Bearbeiten]

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[Bearbeiten]

Warnung
Das Verwenden der klassischen MySQL-Funktionen ist nicht empfehlenswert, da sie veraltet und unsicher sind.

Methodenübersicht[Bearbeiten]

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[Bearbeiten]

<?php
// Verbindung erstellen, bei Fehler diesen ausgeben:
$link = mysql_connect('localhost', 'user', 'passwort') or die(mysql_error());

// Datenbank auswählen
mysql_select_db('test') or die(mysql_error());

// Tabelle adresse mit den Spalten id, name, strasse, ort und tel erstellen: (adress_id ist Primärschlüssel)
mysql_query('CREATE TABLE adresse (
                 adress_id INT UNSIGNED AUTO_INCREMENT ,
                 name VARCHAR(100) ,
                 strasse VARCHAR(100) ,
                 ort VARCHAR(100) ,
                 tel VARCHAR(20) ,
                 PRIMARY KEY (adress_id)
               )
            ') or die(mysql_error());

// Datensatz einfügen, bei Fehler diesen ausgeben:
mysql_query('INSERT INTO
                 adresse(name, strasse, ort, tel)
             VALUES (
                 "Hans Meier", 
                 "Bahnhofstrasse 1",
                 "4391 Testingen",
                 "010 100 01 01")
            ') or die (mysql_error());

// Datensatz auslesen:
$daten = mysql_query('SELECT
                          name,
                          tel,
                          ort
                      FROM
                          adresse
                     ') or die (mysql_error());

// Datensatz in array speichern:
$daten = mysql_fetch_assoc($daten);

// Tabelle löschen:
mysql_query('DROP TABLE adresse');

// Verbindung schliessen:
mysql_close($link);

// Array ausgeben:
echo "<pre>";
var_dump($daten);
echo "</pre>";
?>

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)

<?php
// Connect, SelectDB und disconnect siehe oberes Beispiel

// Datensätze in 3-dimensionalem Array speichern:
while ($row = mysql_fetch_assoc($daten))
   $daten[] = $row;

// Array ausgeben:
echo "<pre>";
var_dump($daten);
echo "</pre>";
?>

Verwendung von MySQLi[Bearbeiten]

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[Bearbeiten]

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[Bearbeiten]


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.

Glasbutton Warnung.svg

Daten, die aus einer fremden Quelle - in diesem Fall einem Nutzer - stammen, kann niemals vertraut werden!

Arten der Datenübergabe[Bearbeiten]

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?[Bearbeiten]

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[Bearbeiten]

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

 <!DOCTYPE html>
 <html>
     <head>
         <title>Eine PHP-Testseite</title>
     </head>
     <body>
         <form action="index2.php" method="post">
             <fieldset>
                 <legend>Alterseingabe</legend>
                 <label for="alter">Geben Sie bitte Ihr Alter an</label>
                 <input type="text" name="alter" id="alter" />
                 <input type="submit" value="OK" />
             </fieldset>
         </form> 
     </body>
 </html>

Wichtig ist dabei das Attribut method="post" im form-Tag. In die "index2.php" schreiben Sie:

 <?php
 $ausgabe = 'Sie sind ';
 $ausgabe .= htmlspecialchars($_POST['alter']);
 $ausgabe .= ' Jahre alt'; 
 echo $ausgabe;
 ?>

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[Bearbeiten]

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)

Glasbutton Warnung.svg

Gehen Sie immer davon aus, dass die Daten, die Sie gerade empfangen haben, manipuliert sind und Sonderzeichen enthalten, die den Programmablauf verändern können.

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'] : '';
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.
htmlentities($_GET['alter'],ENT_QUOTES);
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();
    htmlentities($_GET['alter'],ENT_QUOTES);
    
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.
mysql_real_escape_string($_GET['alter']); //- Ersetzt spezielle Zeichen - ' wird zu \'

Vorher sollte man jedoch prüfen, ob durch Konfigurationseinstellungen von PHP externe Daten bereits maskiert werden:

function mysql_escape(&$string)
{
  if (get_magic_quotes_gpc())
  {
    $string = stripslashes($string);
  }
  
  mysql_real_escape_string($string);
}

array_walk($_GET, 'mysql_escape');

Die PHP-interne Funktion array_walk() 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.

addslashes() ist möglicherweise unzureichend!



Websiteentwicklung: PHP: $ GET

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[Bearbeiten]

Ein einfaches Beispiel Kreis.php könnte wie folgt aussehen:

<!DOCTYPE html>
<html>
<head>
<title>Kreisberechnung mit PHP</title>
<?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
      }
    }
  }
?>
</head>
<body>
<?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'; 
}
?>
</body>
</html>

Erläuterung[Bearbeiten]

Die Methode $_GET[]; übernimmt die Variablen aus der Kommandozeile (Adresszeile des Browsers)

Beispiel:

 http://servername/ordner/dateiname.php?variablenname=variablenwert

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:

$variable = $_GET['variable'];
$variable2 = $_GET['variable2'];
Im weiteren Verlauf des PHP Documentes kann dann der Inhalt der PHP Variablen verarbeitet, und in einem vom Interpreter generiertem HTML-Document mit
echo "auszugebender String als HTML code";
ausgegeben werden s.o.

Die Übergabe von mehr als einem Parameter[Bearbeiten]

Es ist möglich, mehr als eine Variable zu übergeben. Dafür muss die bestehende URL einfach um ein &, gefolgt von variable=Wert, erweitert werden.

Beispiel:

kreis.php?r=15&einheit=cm&name=Hans

$_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[Bearbeiten]

Die Werte der Variablen können dann mit dem Zuweisungsoperator einer gültigen PHP-Variablen zugewiesen werden:

Beispiel:

$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.

Aufruf per Adressleiste des Browsers[Bearbeiten]

In diesem Beispiel muss die Variable r 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
$_GET['Hans'];
geschrieben.

Aufruf über einen Link[Bearbeiten]

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:

 
<!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>

funktioniert (gegebenenfalls ist der Pfad zur Datei anzupassen).

Aufruf über ein Formular[Bearbeiten]

Enthält ein HTML-Formular im form-Tag das Attribut method="get", so erzeugt PHP beim Submit automatisch für alle Formularelemente in der globalen Array-Variable $_GET einen Eintrag. Der Wert eines Formularelementes <input name="eingabe"> ist also nach Submit über $_GET["eingabe"] zugreifbar.

Nachteile von $_GET[Bearbeiten]

Da es bei
$_GET['Variablenname'];
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
$_POST['Variablenname'];
besser geeignet, weil der User hier nicht wissen muß wie die Daten übergeben werden.

Escapen von Zeichen[Bearbeiten]

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:

echo "Dieses ist ein ausgegebener \"Text\" bei dem das Wort \"Text\" in Redezeichen ausgegeben werden soll!";

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[Bearbeiten]


Websiteentwicklung: PHP: $ POST


Der Array $_POST[] enthält den Inhalt von Variablen aus einem anderem 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.

<!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>

Dann wird der Inhalt der Variablen (des Textfeldes) im PHP-Dokument, dessen Code in ein HTML-Grundgerüst eingebettet ist, verarbeitet:

<!DOCTYPE html>
<head>
<title>Verarbeitung und Ausgabe des Ergebnisses</title>
</head>
<body>
<?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'; 
}
?>
</body>
</html>

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 action="Dateiname.php" nur der Dokumentenname stehen soll.



Websiteentwicklung: PHP: Cookies

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[Bearbeiten]

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():

setcookie($cookiename [,$cookiewert [,$verfallszeitpunkt [,$cookiepfad [,$domain [, $sicherheit]]]]);

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 [HTTPS]-Verbindungen zur Verfügung.

Zu Cookies ein kleines Beispiel:

<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>

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 Datenübergabe)

Hier die Datei "cookie2.php":

<?php
 if(isset($_POST["name"]) && ! empty($_POST["name"]))
 {
     setCookie("name",$_POST["name"],time()+2592000);
 }
?>

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:

<?php
 if(isset($_COOKIE["name"]))
 {
     echo "Hallo ".htmlspecialchars($_COOKIE["name"]).", Du siehst, ich habe deinen Namen nicht vergessen!";
 }
?>

Sitzungscookies[Bearbeiten]

Sitzungscookies verfallen automatisch, wenn der Browser geschlossen wird. Um solche Cookies zu erstellen, lasse einfach den Wert für den Verfallszeitpunkt weg:

 setCookie("name","Klaus");

Cookies per Skript löschen[Bearbeiten]

Cookies können gelöscht werden, indem einfach ein negativer Wert als Verfallszeitpunkt angegeben wird:

 setCookie("name","",-3600);



Websiteentwicklung: PHP: Sessions

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[Bearbeiten]

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.

<?php
//starten der Session
session_start();
?>


Variablen belegen[Bearbeiten]

Die Variablen können genau wie jede andere normale Variable belegt werden. Sie werden mit $_SESSION['beliebiger Name'] benannt.

<?php
//starten der Session
session_start();

//belegen einer Variablen
$_SESSION['USER_ID'] = 'Wikimeister';
?>


Variablen abrufen[Bearbeiten]

Mit dem Namen $_SESSION['beliebiger Name'] lässt sich die Variable jederzeit abrufen sofern die Session gesetzt ist und der Browser nicht geschlossen wurde.

<?php
//starten der Session
session_start();

//belegen einer Variablen
$_SESSION['USER_ID'] = 'Wikimeister';

//abrufen einer Variablen
echo $_SESSION['USER_ID'];
?>

Ausgabe: Wikimeister


Sessionvariablen löschen[Bearbeiten]

Die Werte, die in der Session gespeichert sind, können auf verschiedene Arten gelöscht werden.

Löschen der ganzen Session mittels session_destroy();[Bearbeiten]

<?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();
?>

Anmerkung: Hier werden alle Variablen in der Session bzw. die Session selbst gelöscht.


Löschen einzelner Variablen mittels unset();[Bearbeiten]

<?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']);
?>


Weiterführende Weblinks[Bearbeiten]


Websiteentwicklung: PHP: OOP

Was ist OOP?[Bearbeiten]

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:

Hinweis

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.
  <?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();
  
  ?>

Dieser Code erzeugt folgende Ausgabe:

Ich bin 5 Meter hoch. Ich hatte schon bessere Tage. Ich bin 15 Meter hoch.

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[Bearbeiten]

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[Bearbeiten]

Ein Konstruktor ist die Funktion, die beim Erzeugen eines Objekts aufgerufen wird, sie heißt __construct() (Der doppelte Unterstrich weist auf eine Magische Methode hin.) In PHP 4 wurde stattdessen der Name der Klasse verwendet.

  <?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();
  
  ?>

Das erzeugt folgende Ausgabe:

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.

Foo hat also zwei Bäume und einen Tisch interviewt.


Websiteentwicklung: PHP: Eigenschaften

Eigenschaften[Bearbeiten]

Unsere erste Klasse[Bearbeiten]

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 am Besten OOP vermitteln. Du kannst jetzt also deine allererste Klasse „Baum“ schreiben:

<?php

class Baum {
}

?>

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:

<?php
require_once 'Baum.php';
?>

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[Bearbeiten]

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 new:

<?php
require_once 'Baum.php';

$bar = new Baum();
?>

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:

var_dump($bar);

Du erhältst diese Ausgabe:

 object(Baum)[1]

Eigenschaften deklarieren[Bearbeiten]

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:

<?php

class Baum {

  public $hoehe;
  public $gesundheit;

}

?>

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.

Du kannst auch bestimmen, dass Standardwerte vergeben werden, z.B. für einen gesunden Keim:

  public $hoehe = 0.1;
  public $gesundheit = 100;

Lass dir das Ergebnis anzeigen, und du wirst sehen, dass alle Objekte dieser Klasse mit diesen Standardwerten starten.

Auf Eigenschaften zugreifen[Bearbeiten]

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

echo $bar->hoehe;
echo '<br />';
echo $bar->gesundheit;

und du wirst lesen können:

0.1
100

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:

$bar->gesundheit = $bar->gesundheit - 30;

oder in der Kurzschreibweise:

$bar->gesundheit -= 30;

Später werden wir auch ein Objekt des Helden erzeugen, um den Vorgang eines Schlags mit dem Schwert zu realisieren.

Der Typ-Operator instanceof[Bearbeiten]

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 instanceof:

if ($bar instanceof Feind) {
  
  // Feind: angreifen
  $bar->gesundheit = $bar->gesundheit - 30;

} else {
  
  // Freund: guten Tag sagen
  echo 'Seid gegrüßt!';

}

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[Bearbeiten]

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:

<?php

class Baum {

  public $hoehe;
  public $gesundheit;

  const  KANN_REDEN = true;

}

?>

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:

<?php
require_once 'Baum.php';

if (Baum::KANN_REDEN == true)
{
  echo 'Ja, kann reden.';
} else
{
  echo 'Schweigt sich aus.';
}
?>

Wenn alles stimmt, sollte als Ausgabe "Ja, kann reden." zu sehen sein.

Sichtbarkeit[Bearbeiten]

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:

<?php

class Baum {

  public $hoehe;
  protected $gesundheit;

}

?>

Versuchen wir jetzt, uns den Gesundheitszustand des Baumes anzusehen:

<?php
require_once 'Baum.php';

$bar = new Baum();
echo $bar->gesundheit;
?>

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:

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.

Glasbutton Warnung.svg

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 (Interfaces), sodass man die Klasse verwenden kann, ohne ihre konkrete Implementierung zu kennen

In den Beispielen dieses Buches wird allerdings weiterhin direkt auf die Objekteigenschaften zugegriffen, um den Code möglichst gut lesbar zu gestalten.

PHP-Dokumentatiton[Bearbeiten]

Folgende Abschnitte der PHP-Dokumentatition wurden in diesem Kapitel behandelt:


Websiteentwicklung: PHP: Methoden

Methoden[Bearbeiten]

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[Bearbeiten]

Wir können unsere Klasse um eine Methode sagHallo erweitern, um den Klassiker aller Programmierbeispiele zu implementieren:

<?php

class Baum {

  public $hoehe;
  protected $gesundheit;

  const  KANN_REDEN = true;

  public function sagHallo() {

    echo 'Hallo Welt!';

  }

}

?>

Wenn wir jetzt in unserer Indexseite schreiben

<?php
require_once 'Baum.php';

$bar = new Baum();
$bar->sagHallo();
?>

erhalten wir die erwartete Ausgabe

Hallo Welt!

Wie du nebenbei sicher bemerkt hast, gilt die von Eigenschaften bekannte Sichtbarkeit auch für Methoden.

Statische Eigenschaften und Methoden mit self[Bearbeiten]

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:

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
  }
}

Die Ausgabe bleibt gleich, da der Baum reden kann.

Objekteigenschaften und -methoden mit $this[Bearbeiten]

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:

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. */
  }

}

Wie du siehst, greift die Methode mit $this auf ihre eigene Eigenschaft zu. Wenn du jetzt wissen willst, wie es dem Baum geht

echo $bar->sage_mir_dein_wohlbefinden();

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.

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;
  }
}

Parameter funktionieren hier genauso wie bei Funktionen. Wir können jetzt testweise die Gesundheit erhöhen und senken:

<?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();

?>

Ausgabe:

Mir geht es echt mies.
Ich hatte schon bessere Tage.
Mir geht es super.
Ich bin ein Tisch.

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[Bearbeiten]

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:

<?php
class Welt {
  protected $baum;
  
  public function pflanzeBaum($baum) {
    $this->baum = $baum;
  }
  
  public function setzeBaumhoehe() {
    $this->baum->hoehe = 10;
  }
}
?>

Führen wir nun in der Indexseite diesen Code aus:

<?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;

?>

Als Ergebnis erhalten wir

5
10

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:

$ber = clone $bar;

Type Hinting[Bearbeiten]

Spielen wir doch einmal Matrjoschka (auch als russische Puppe bekannt) und pflanzen wir anstatt des Baumes eine Welt in eine Welt:

<?php
require_once 'Baum.php';
require_once 'Welt.php';

$welt  = new Welt();
$welt2 = new Welt();
$welt->pflanzeBaum($welt2);
$welt->setzeBaumhoehe();
echo $welt2->hoehe;

?>

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

10

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' => int 10

Wie können wir also verhindern, dass die Welt stur jedes Objekt einpflanzt? Die Antwort lautet Type Hinting. Wir sagen bei Angabe der Paramter in der Methode, die Instanz welcher Klasse das Objekt sein soll:

public function pflanzeBaum(Baum $baum) {
  $this->baum = $baum;
}

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 Interfaces.

PHP-Dokumentation[Bearbeiten]

Folgende Abschnitte der PHP-Dokumentation wurden in diesem Kapitel behandelt:


Websiteentwicklung: PHP: Magische Methoden

Magische Methoden[Bearbeiten]

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[Bearbeiten]

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:

<?php
class Welt {
  protected $baum;
 
  public function __construct(Baum $baum) {
    $this->baum = $baum;
  }
 
  public function setzeBaumhoehe() {
    $this->baum->hoehe = 10;
  }
}
?>

Wie du siehst, haben wir einfach die Methode pflanzeBaum in __construct umbenannt. Um nun eine Welt zu erzeugen, verwenden wir folgenden Code:

<?php
require_once 'Baum.php';
require_once 'Welt.php';
 
$bar = new Baum();
$welt = new Welt($bar);
?>

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 Singleton-Pattern.

__destruct[Bearbeiten]

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:

public function __destruct() {
  echo 'Ein(e) '.__CLASS__.' wurde zerstört!';
}

Wenn du jetzt deinen Code von oben aufrufst, wird ausgegeben:

Ein(e) Welt wurde zerstört!

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[Bearbeiten]

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:

<?php
require_once 'Baum.php';
require_once 'Welt.php';

$ber = new Baum();
$welt = new Welt($ber); 
$welt->drehe_um_winkel(50);
?>

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:

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__);
  }
}

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 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 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[Bearbeiten]

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:

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[Bearbeiten]

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:

public function __sleep() {
  return array('hoehe');
}

Jetzt setzen wir noch die Gesundheit nach dem Aufwachen auf 100:

public function __wakeup() {
  $this->gesundheit = 100;
}

Und schon haben wir einen erholten Baum:

<?php
require_once 'Baum.php';

$ber = new Baum();
$speicher = serialize($ber);
$ber = unserialize($speicher);
echo $ber->sage_mir_dein_wohlbefinden();
?>
Mir geht es super.

__toString[Bearbeiten]

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:

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

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[Bearbeiten]

__clone[Bearbeiten]

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 Methoden gezeigt, das Schlüsselwort clone verwenden:

<?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;
?>

Als Ausgabe erhalten wir

10

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 die selbe Instanz von Baum. Der Baum steht also zur gleichen Zeit auf zwei verschiedenen Welten. Da wir nicht Quantenphysik betreiben wollen, ändern wir dieses Verhalten:

// Vorhergehender Code der Klasse Welt

  public function __clone() {
    $this->baum = clone $this->baum;
  }

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)[Bearbeiten]

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:

class Ausgabe {

  public function __invoke($text) {
    echo $text;
  }

$ausgabe = new Ausgabe();
$ausgabe('Hallo Welt!');

Ausgabe:

Hallo Welt!

Aufrufbare Objekte geben true zurück, wenn man auf sie die Funktion is_callable anwendet.

PHP-Dokumentation[Bearbeiten]

Folgende Abschnitte der PHP-Dokumentation wurden in diesem Kapitel behandelt:


Websiteentwicklung: PHP: Statische Eigenschaften und Methoden

Statische Eigenschaften und Methoden[Bearbeiten]

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[Bearbeiten]

Wir legen unsere ziemlich angewachsene Klasse Baum für einen Moment zur Seite (werden sie aber im Kapitel Vererbung wieder aufgreifen) und basteln uns eine neue Klasse Apfel:

<?php

class Apfel {
  public static $anzahl_aepfel = 0;
  public $farbe;

  public function __construct($farbe) {
    self::$anzahl_aepfel++;
    $this->farbe = $farbe;
  }
}

?>

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':

<?php
require_once 'Apfel.php';

$apfelkorb[] = new Apfel('rot');
$apfelkorb[] = new Apfel('gelb');
$apfelkorb[] = new Apfel('gruen');

echo Apfel::$anzahl_aepfel;
?>

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[Bearbeiten]

Statische Methoden werden analog zu statischen Eigenschaften deklariert. Implementieren wir also einen Getter für die statische Eigenschaft $anzahl_aepfel


<?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;
  }
}

und rufen diese Methode auf:

<?php
require_once 'Apfel.php';

$apfelkorb[] = new Apfel('rot');
$apfelkorb[] = new Apfel('gelb');
$apfelkorb[] = new Apfel('gruen');

echo Apfel::getAnzahl_aepfel();
?>

Dies führt zur gleichen Ausgabe.

Variable Klassennamen bei statischen Aufrufen (PHP 5.3)[Bearbeiten]

Ab PHP-Version 5.3 können statische Aufrufe auch mit einem variablen Klassennamen geschehen. Folgender Aufruf wäre äquivalent zum obigen Beispiel:

<?php
require_once 'Apfel.php';

$apfelkorb[] = new Apfel('rot');
$apfelkorb[] = new Apfel('gelb');
$apfelkorb[] = new Apfel('gruen');

$name = 'Apfel';

echo $name::getAnzahl_aepfel();
?>

Späte statische Bindung (PHP 5.3)[Bearbeiten]

Ebenfalls neu seit PHP-Version 5.3 ist die späte statische Bindung („Late static binding“). Erbt eine Klasse von einer anderen, wird der Kontext von self normalerweise auf die Vaterklasse angewendet. Ein Beispiel:

<?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();

?>

Dies erzeugt die Ausgabe

Hallo!

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:

<?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();

?>
Seid gegrüßt!

Singleton-Pattern[Bearbeiten]

Einen praktischen Einsatz von statischen Eigenschaften und Methoden zeigt das Singleton-Pattern, welches sicherstellt, dass nur eine Instanz einer Klasse vorhanden ist und global darauf zugegriffen werden kann.

PHP-Dokumentation[Bearbeiten]

Folgende Abschnitte der PHP-Dokumentation wurden in diesem Kapitel behandelt:


Websiteentwicklung: PHP: Vererbung

Vererbung[Bearbeiten]

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:

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. */
  }
 
}

Das Schlüsselwort extends[Bearbeiten]

Vererbung geschieht in PHP mittels des Schlüsselworts extends:

class Kastanie extends Baum {
}

$kastanie = new Kastanie();
echo $kastanie->sage_mir_dein_wohlbefinden();

Ausgabe:

Ich bin ein Tisch.

Wie du siehst, hat die Kastanie alle Methoden der Klasse Baum geerbt.

Überschreiben von Methoden und Eigenschaften[Bearbeiten]

Eigenschaften können von der Kindklasse auch überschrieben und so mit neuen Werten belegt werden:

class Kastanie extends Baum {

protected $gesundheit = 100;

}

$kastanie = new Kastanie();
echo $kastanie->sage_mir_dein_wohlbefinden();
Mir geht es super.

Genau so können Methoden ebenfalls überschrieben werden, beispielsweise, weil unsere Kastanie unhöflich ist und niemals Hallo sagt:

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');

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[Bearbeiten]

PHP kann keine Mehrfachvererbung, d.h., eine Klasse kann immer nur von einer einzigen Klasse abgeleitet werden. Allerdings kannst du Vererbungen aneinander ketten:

class Rosskastanie extends Kastanie {
}

Somit ist die Vererbungssequenz: Baum => Kastanie => Rosskastanie.

Selbstverständlich kann aber eine Elternklasse mehrere Kinder haben:

class Buche extends Baum {};
class Esche extends Baum {};
// ...

Type Hinting und Vererbung[Bearbeiten]

Abgeleitete Klassen erfüllen Type Hints der Elternklasse. Die Methode

public function __construct(Baum $baum) {
  $this->baum = $baum;
}

in der Klasse Welt kann auch mit einer Rosskastanie gültig aufgerufen werden:

$kastanie = new Rosskastanie();
$welt = new Welt($kastanie);

Auf überschriebene Methoden zugreifen[Bearbeiten]

Ü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:

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. */
  }
}

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:

class Spiegelbaum extends Baum {
  public function sage_mir_dein_wohlbefinden() {
    return strrev(parent::sage_mir_dein_wohlbefinden());
  }
}
Tipp:

Glasbutton Tipp.svg

Besonders hilfreich ist diese Möglichkeit bei Objekten, die andere Objekte per Konstruktor in sich kapseln (z.B. der Controller im MVC-Modell), aber davon abgeleitete Klassen auch mehr Objekte haben können:

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);
  }
}


Abstrakte Klassen und Methoden[Bearbeiten]

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:

abstract class Baum {
// vorhergehender Code
}

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:

class Buche extends Baum {
}

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:

abstract class Baum {

  abstract public function sagHallo();

// restlicher Code
}

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:

class Buche extends Baum {
  public function sagHallo() {
    echo '"Hallo", sagte die Buche.';
  }
}

Finale Klassen und Methoden[Bearbeiten]

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:

class Baum {
  final public function sage_mir_dein_wohlbefinden()
  {
    // Inhalt der Methode
  }
}

class Buche extends Baum {
  public function sage_mir_dein_wohlbefinden()
  {
    return false;
  }
}

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:

final class Baum {
}

class Kastanie extends Baum {
}

Auch das ist ein Fehler:

 Fatal error: Class Kastanie may not inherit from final class (Baum)

PHP-Dokumentation[Bearbeiten]

Folgende Abschnitte der PHP-Dokumentation wurden in diesem Kapitel behandelt:


Websiteentwicklung: PHP: Interfaces

Interfaces[Bearbeiten]

Schau dir einmal die folgende Klasse an:

class Versammlung {

  protected $sprecher = array();

  public function neuerSprecher($sprecher) {
    $this->sprecher[] = $sprecher;
  }

  public function alleStellenSichVor() {
    foreach ($this->sprecher as $sprecher) {
      $sprecher->sagHallo();
      echo '<br />';
    }
  }
}

Im Kapitel Methoden hatten wir dem Baum die Methode sagHallo gegeben. Somit können wir folgenden Code problemlos ausführen:

$baum = new Baum();
$versammlung = new Versammlung();
$versammlung->neuerSprecher($baum);
$versammlung->alleStellenSichVor();

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[Bearbeiten]

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[Bearbeiten]

interface Sprecher {
  public function sagHallo();
}

Unser Baum kann nun dieses Interface mit dem Schlüsselwort implements implementieren:

class Baum implements Sprecher {
// restlicher Code
}

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[Bearbeiten]

TypeHinting kann auch für Interfaces verwendet werden:

//...
public function neuerSprecher(Sprecher $sprecher) {
//...

Auch der Operator instanceof funktioniert mit Interfaces.

Mehrere Interfaces[Bearbeiten]

Nun braucht unsere Versammlung noch einen Vorstand, der die Versammlung eröffnet. Mit ein paar Änderungen sieht unsere Klasse nun so aus:

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();
  }
}

Nun brauchen wir das Interface Vorstand, welches die Methode verleseTagesordnung zwingend vorschreibt:

interface Vorstand {
  public function verleseTagesordnung();
}

Zum Schluss erweitern wir noch die Klasse Baum, sodass sie sowohl als Sprecher, wie auch als Vorstand auftritt:

class Baum implements Sprecher, Vorstand {

//...

public function verleseTagesordnung() {
  echo 'Punkt 1: Held Foo zum Ehrenmitglied ernennen. Punkt 2: ...';
}

Jetzt ist die Versammlung bereit, abgehalten zu werden:

$baum = new Baum();
$versammlung = new Versammlung();

$versammlung->neuerSprecher($baum);
$versammlung->setzeVorstand($baum);

$versammlung->alleStellenSichVor();
$versammlung->eroeffnen();

Ausgabe:

Hallo Welt!
Punkt 1: Held Foo zum Ehrenmitglied ernennen. Punkt 2: ...

Interfaces und Vererbung[Bearbeiten]

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:

interface Vorstand extends Sprecher { //...

PHP-Dokumentation[Bearbeiten]

Folgender Abschnitt der PHP-Dokumentation wurde in diesem Kapitel behandelt:


Websiteentwicklung: PHP: Autoloading

Autoloading[Bearbeiten]

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:

<?php

require_once 'Kastanie.php';
require_once 'Welt.php';
require_once 'Foo.php';

$baum = new Kastanie();
$welt = new Welt($baum);
$held = new Foo();

?>

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 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[Bearbeiten]

PHP benötigt dafür eine Autoload-Funktion. Diese Funktion hat einen Parameter, die den kompletten Klassen- oder Interfacenamen (inklusive eventuell aufgelöster 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[Bearbeiten]

Einen solchen Autoloader kann mit der magischen Funktion __autoload() bereitstellen.

<?php

function __autoload($klassenname) {
  $pfad = 'classes/' . $klassenname . '.php';
  
  if (file_exists($pfad)) {
    /**
    * Wer ausschließlich Autoloading verwendet, kann auf "_once" verzichten,
    * da die Funktion nur einmal pro Klasse aufgerufen wird.
    */
    require_once $pfad;
  } else {
    return false;
  }
}

$held = new Foo();
$baum = new Kastanie();

//...

?>

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 voraussetzen.

spl_autoload_register (PHP-Version >= 5.1.2)[Bearbeiten]

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, solltest du besser eine anders benannte Funktion verwenden. Das kann, wegen des callback-Typs, auch eine Objekt- oder statische Methode sein:

<?php

// Datei: classes/fantasyAutoloader.php

class fantasyAutoloader {

  public static function load($klassenname) {
    $pfad= __DIR__ . DIRECTORY_SEPARATOR . $klassenname . '.php';
  
    if (file_exists($pfad)) 
    {
      require_once $pfad;
    } 
    else 
    {
      return false; 
    }
  }
}

// Datei: index.php

require_once 'classes/fantasyAutoloader.php';

spl_autoload_register(array('fantasyAutoloader', 'load'));

$held = new Foo();

//...

?>

Somit können andere Pakete ebenfalls ihre Autoloader mit spl_autoload_register registrieren.

Lösungen für Verzeichnisbäume[Bearbeiten]

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[Bearbeiten]

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):

<?php

class Person_Held_Foo extends Person_Held_Abstract {

//...

}

Dementsprechend funktioniert der Autoloader so:

<?php

function pfadImKlassennamen($klassenname) {
  $ordner = explode('_', $klassenname);
  $pfad = 'classes/' . implode('/', $ordner) . '.php';

  if (file_exists($pfad)) {
    require_once $pfad;
  } else {
    return false;
  }
}

?>

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[Bearbeiten]

Mit der Version 5.3 wurden in PHP die Namespaces eingeführt. Sie verhindern Überschneidungen in der Benennung von Klassen und bieten sich durch ihre Pfadstruktur geradezu für das Autoloading an:

<?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);
  
  $pfad = implode(DIRECTORY_SEPARATOR, $teile) . '.php';

  if (file_exists($pfad)) {
    require_once $pfad;
  } else {
    return false;
  }
}

?>

Generierte Liste der Klassen[Bearbeiten]

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:

<?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];
}

?>

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 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[Bearbeiten]

Folgende Abschnitte der PHP-Dokumentation wurden in diesem Kapitel behandelt:


Websiteentwicklung: PHP: Traits

Traits[Bearbeiten]

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.

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();

Ausgabe:

Hallo Welt! In Klasse 1
Hallo Welt! In Klasse 2

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:

use Hallo, Welt;

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[Bearbeiten]

Durch eine "use" Anweisung kann man ebenfalls die folgenden Dinge machen:

Konfliktauflösung[Bearbeiten]

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;
    }
}

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[Bearbeiten]

trait Foo {
    public function Bar() {
        echo 'Hallo Welt!';
    }
}

class Klasse1 {
    use Foo { Bar as private }
}

class Klasse2 {
    use Foo {Bar as private FooBar }
}

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[Bearbeiten]

Traits können auch das "use" Konstrukt benutzen um einen anderen Trait zu implementieren:

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();

Ausgabe:

Hallo Welt! Zweiter Trait

Weitere Möglichkeiten in Traits[Bearbeiten]

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:

trait FooBar {
    public $foo = "Bar";
}

Die Eigenschaften können dann von der Klasse die diesen Trait implementiert nicht mehr überschrieben werden.

PHP-Dokumentation[Bearbeiten]

Folgender Abschnitt der PHP-Dokumentation wurde in diesem Kapitel behandelt:


Websiteentwicklung: PHP: Dependency Injection

Dependency Injection[Bearbeiten]

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):

class MyController {

    private $logger;

    public function __contruct() {
        $this->logger = new Logger();
    }

    public function myAction() {
        $this->logger->log("someone called myAction");
    }
}

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

Desweiteren 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[Bearbeiten]

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:

class MyController {

    private $logger;

    public function __construct(Logger $logger) {
        $this->logger = $logger;
    }

    public function myAction() {
        $this->logger->log("someone called myAction");
    }
}

An der Stelle, wo MyController instanziiert wird, muss nun eine Instanz der Klasse Logger übergeben werden:

$logger = new Logger();

$myController = new MyController($logger);

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:

$logger = new Logger();
$logger->setTargetPath('/my/log.txt');
$logger->setLogLevel(2);

$myController = new MyController($logger);

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[Bearbeiten]

Anwendungsfall: Wenn die Abhängigkeit an bestimmten Stellen benötigt wird und vorher bekannt ist, ob das der Fall ist. Desweiteren 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.

$logger = new Logger();

$myController = new MyController();
$myController->setLogger($logger);

Die Klasse MyController sähe wie folgt aus:

class MyController {

    private $logger;

    public function setLogger(Logger $logger) {
        $this->logger = $logger;
    }

    public function myAction() {
        $this->logger->log("someone called myAction");
    }
}

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[Bearbeiten]

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[Bearbeiten]

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:

interface LoggerInterface {
    public function log($message);
}

Dieses muss nun von der Logger-Klasse implementiert werden.

Nun können wir die Type Hints austauschen: Logger wird zu LoggerInterface:

class MyController {

    private $logger;

    public function setLogger(LoggerInterface $logger) {
        $this->logger = $logger;
    }

    public function myAction() {
        $this->logger->log("someone called myAction");
    }
}

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. Desweiteren 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.


Websiteentwicklung: PHP: Muster Singleton


Singleton[Bearbeiten]

Erzeugt genau eine Instanz eines Objektes. (vgl. 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[Bearbeiten]

 <?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() {}
 }
 ?>

Beispiel[Bearbeiten]

Das folgende Beispiel soll verdeutlichen, wie die oben beschriebene Implementierung verwendet wird.

<?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;
 
 ?>


Ausgabe

 $demo1: $value = 5
 $demo2: $value = 5

Weblinks[Bearbeiten]


Websiteentwicklung: PHP: Observer

Implementierung (ab Version 5)[Bearbeiten]

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);
I'm observer 1 and value is 1
I'm observer 2 and value is 1
I'm observer 2 and value is 2


Websiteentwicklung: PHP: Dateisystem

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[Bearbeiten]

Hier ein Beispiel für einen Besucherzähler mithilfe von Dateisystemfunktionen:

 <?php
    $counter = file_get_contents("counter.txt");        
    $counter++;
 
    $f = fopen("counter.txt", "w");
    fwrite($f,$counter,10);
    fclose($f);
 
    readfile("counter.txt");
 ?>

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.


Websiteentwicklung: PHP: Zugriff auf andere Webseiten

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:

<?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);
?>


Websiteentwicklung: PHP: Mails

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[Bearbeiten]

Die Mail-Funktion kann genutzt werden, um automatisch E-Mails zu verschicken.

<?php
    mail('mustermann@beispiel.de', 'Betreff', 'Nachricht');
?>

Hiermit wird eine E-Mail an mustermann@beispiel.de mit dem Betreff "Betreff" und der Nachricht "Nachricht" versandt.

<?php