Einführung:
Ich heiße Dich willkommen und freue mich, daß Du Interesse gefunden hast, mein Tutorial anzugucken. Erstmal möchte ich natürlich festlegen, wem das Tutorial hilfreich sein könnte und was genau das Ziel ist.
Wenn erstmal die Zeit reif wird, in der man in der Lage ist eigene Scripte mit PHP zu entwerfen, stellt sich die Frage ob man nun viel/genug weiß, oder gibt es noch etwas, was PHP zu bieten hat? Die Antwort lautet eindeutig: "Ja, und ob!". Man lernt nie aus, egal in welcher Branche man sich befindet. Als Anfänger lernt man die Sprachkonstrukte der Sprache, die Benutzung und Sinn dessen. Die Praxis fördert dann eine Denkweise beim Entwurf und Verwirklichung von Ideen, die sich streng an den gelernten Stoff hällt - die Möglichkeiten und Einsatzgebiete der Sprache. Oft wird ein falscher Weg genommen und man lernt die Funktionen auswendig, was natürlich bedingt Fortschritte in der Entwicklung bringt und man auch nicht begreift, wozu PHP fähig ist.
Ohne, dass ich jetzt als Einführung einen Roman verfasse, zähle ich die Punkte auf, die als Voraussetzung dienen sollten, um mit dem Tutorial was anfangen zu könen:
- Du hast mit PHP bereits einige (kleine) Projekte entwickelt
- Du möchtest tiefer in PHP eindringen, Theorie verstehen
Logik und Sinn einer Programmiersprache
Zwar ist PHP keine echte Programmiersprache, aber dennoch kann man sowohl eine schlechte wie auch eine gute Anwendung/Script damit schreiben. Aber wo sind die Grenzen von gut und schlecht? Unter schlecht kann/sollte man eine leichtsinnige, unüberlegte, „draufgemotzte“ Software vorstellen, die ohne sich als Programmierer Gedanken über das Design des Codes zu machen erstellt wurde. Eine gute braucht dagegen viel mehr als das. Aber das ist auch die Kunst, nach der ein guter Programmierer streben sollte.
Ich möchte jetzt auf Einzelheiten von PHP eingehen, die oft gar nicht beachtet werden und daher auch viele Fehler hervorrufen können, die nicht immer gleich erkennbar sind.
1 Operatoren
Operatoren sind in Programmiersprachen die Schnittstelle für den Programmierer, wenn es um logische Zusammenhänge geht. Daher liegt es klar auf der Hand, dass man damit bereits ein mächtiges Werkzeug hat, was aber auch unter Umständen zur Verwirrung führen kann. Lange Ausdrücke brauchen oftmals Klammern, um vor anderen Teilen des Ausdrucks ausgewertet zu werden. Zu beachten ist hier auch die Rangfolge von Operatoren. Es würde nichts als Unfug entstehen, wenn Operatoren diese nicht hätten.
Es folgen ein paar Beispiele:
PHP-Code:
// Rangfolge der Operatoren
$a = 5;
$b = 10;
$a + $a * 2 || 2 * $a + $a; // Ausdruck 1
$a == 10 && $a; // Ausdruck 2
$a == $a && 10; // Ausdruck 3
$b += $a != 10 + $a; // Ausdruck 4
Versuche diese vier Ausdrücke im Kopf zu durchlaufen. Danach kannst Du die Ausdrücke in einem PHP-Script ansehen. Stimmen die Ergebnisse überein? Wenn ja, dann arbeitest du wie ein PHP-Parser und zwar Schritt für Schritt. Sollten verschiedene Ergebnisse deine Welt in den Wahnsinn treiben – keine Panik, für alles gibt es eine logische Erklärung!
Im Ausdruck 1 werden der Operator +, * und || benutzt. Um auf ein Ergebnis zu gelangen, muss man wissen was zuerst zusammengefasst und ausgewertet wird. Dabei geht es nach der Priorität der drei Operatoren. Höchstens in der 6. Klasse weiß man, dass „Punkt- vor Strichrechnung“ kommt, was in PHP auch nicht anders ist. PHP wertet zuerst die *-, /-, %-Operatoren aus, bevor +, - und . dran sind. Erst danach findet der endgültige Vergleich der beiden Werte mit || statt. Also erhalten wir hier den Wert 1, true um genauer zu sein, da die Vergleichsoperatoren nur bool zurückliefern. Bei dem Ausdruck 2 kann schnell ein Denkfehler entstehen, obwohl da nur zwei Operatoren zur Wahl stehen. Tatsächlich ist der Operator == „stärker“ als && und es wird daher der boolesche Wert von $a == 10 schlussendlich mit dem &&-Operator verglichen, was in unserem Fall zu true führt. Die letzten zwei Beispiele enthalten ebenfalls leichte Verwirrungen, die man aber höchstens nach dem Durchgehen der Rangtabelle im PHP-Handbuch (s. Operatoren->Operator-Rangfolge) bewältigen sollte.
Jedenfalls verwirrend fand ich die Tatsache, dass die Operatoren and und or zwar das gleiche wie && und || tun, allerdings niedrigere Ränge haben, was manchmal vorteilhaft sein kann (häufigste Verwendung von or fiel mir bei „$var = $var2 or die();“ auf).
Was ist eher schlecht an folgendem Design?
PHP-Code:
// if-Verschachtelung
if ($var1)
{
if ($var2)
{
if ($var3)
{
//… usw.
}
}
}
Man versucht in der Hoffnung, dass soweit eine der drei Variablen false liefert, der Vorgang der weiteren Überprüfung sofort beendet wird, um keinen zusätzlichen Laufzeitaufwand zu erzeugen. Dabei wäre die Möglichkeit, die Ausdrücke mit && zusammenzufassen gar nicht schlechter/langsamer, sondern kürzer und übersichtlicher.
PHP-Code:
if ($var1 && $var2 && $var3) { /* … */ }
Sollte $var1 false zurückliefern, wird es gar nicht erst dazu kommen, dass $var2, $var3 auf false überprüft werden. Es bringt uns also keine Nachteile, die kurze Variante zu bevorzugen.
Um es an einem Beispiel zu demonstrieren kann es der Wert einer Funktion sein, die einen String auf Inhalt prüft, bei Erfolg und auch erst danach kann eine weitere Funktion aufgerufen werden, um den gleichen String in die Datenbank einzutragen.
Die meisten haben was von den Bit-Operatoren gehört. Einen Einsatz finden diese allerdings recht selten, vielleicht auch deswegen, weil man sie gar nicht beachtet, wenn eine Lösung gefunden werden soll. Dabei sind gerade diese Operatoren die Logik, der Grundstein für alles, was man mit den anderen Operatoren erreicht. Wie man vielleicht weiß, funktioniert ein CPU nur mit einem Paar an „Schaltungen“, die für den Menschen als logisch erscheinen sollen. Baut man diese weiter auf, so sind der Fantasie (fast) keine Grenzen gesetzt. Doch wo können die Bit-Operatoren eine praktische Verwendung finden?
Sagen wir mal Flags… was fällt uns dazu ein? Also Flags sind einfache Integers, die zur Übersicht als Konstanten definiert sind. Was könnte man denn machen, wenn eine Funktion mehrere von solchen Konstanten erwarten könnte? Sagen wir mal, wenn wir eine Funktion zur Darstellung einer Figur hätten. Es könnte ein Kreis sein, der im 2D, 3D, Farbe, Glanz usw. dargestellt werden könnte. Dabei kann es sein, dass man 3D, Farbe und Glanz in der Ausgabe haben will. Was nun? Sollte man für jede Einstellung einen Parameter anlegen? Und wenn es 10 Einstellungen möglich sein sollten? Eine Hilfe wäre jetzt eine Klasse oder Array, um die Elemente zusammenzufassen. Doch auch da müsste man jedes Mal viel Schreibarbeit anwenden, auch wenn nicht direkt in dem Funktionsrumpf. Angenehmer wäre es, wenn man die Einstellungen in einem Ausdruck übergeben könnte, ohne dafür besondere Methoden anzuwenden. Und da schaffen die Bit-Operatoren eine Abhilfe:
Wenn man bedenkt, dass jede dezimale Zahl vom CPU nur binär verstanden werden kann, heißt es auch, dass die einzelnen Bits sich nur zu verschieben brauchen, damit eine eindeutige Zahl entsteht. Im Dezimalsystem ist das natürlich nicht anders, wenn man 10 um eine Stelle (im Dezimalsystem ist die Basis 10) nach links verschiebt, bekommt man 100. Danach würde 1.000, 10.000… rauskommen. Was diese Tatsache allerdings für das Binärsystem interessant macht ist, dass man unsere Flags mit den Bitoperatoren zusammenfassen kann, auf die gleiche Weise wie das Beispiel mit der Zahl 10 als Basis. Im Binärsystem ist es die 2 als Basis, auf die die Bit-Operatoren auch spezialisiert sind.
Es folgt ein Beispiel mit unserer Funktion für Kreisdarstellung: (vereinfacht)
PHP-Code:
// Konstanten
define('OPTION_2D', 0x1); // Binär: 0001
define('OPTION_3D', 0x2); // Binär: 0010
define('OPTION_FARBE', 0x4); // Binär: 0100
define('OPTION_GLANZ', 0x8); // Binär: 1000
function Zeichne_Kreis($einstellungen)
{
if ($einstellungen & OPTION_2D) { /* … */ }
// …
}
// Aufruf der Funktion und Zusammenfassung von Einstellungen
Zeichne_Kreis(OPTION_2D | OPTION_FARBE | OPTION_GLANZ);
Was wir nun geschaffen haben ist ein zusammengesetzter Wert, der die einzelnen Einstellungen nicht „stört“. Es ist also nicht von Bedeutung, ob ich alle Einstellungen zusammenfasse oder nur eine einzelne an die Funktion übergebe – es wird das getan, was ich an die Funktion als Aufgabe/Argument übergebe. (vorausgesetzt die Funktion verhält sich richtig)
Ich empfehle denen, für die etwas Derartiges neu erscheint den Vorgang genauer anzugucken. Warum wird zum Vergleichen der &- und nicht der ==-Operator verwendet? Was macht man, wenn man den zusammengesetzten Wert auf viele Einstellungen hin in einem Rutsch überprüfen will? (z.B. OPTION_3D und OPTION_2D) (s. PHP-Handbuch->Operatoren->Bit-Operatoren)
Bit-Operatoren werden u.a. in der Kryptografie und Netzwerk verwendet. Interessiert sich einer z.B. für Verschlüsselungstheorien und Algorithmen, so ist es unausweichlich, die Bit-Operatoren zu benutzen.
Fazit: Prinzipiell sollte man immer die Operator-Ränge im Auge behalten, wenn ein komplexer Ausdruck geplant ist. Dabei spielen Klammern eine wichtige und manchmal unausweichliche Rolle.
Bit-Operatoren verstehen können kann nie direkt schaden, es öffnen sich neue Türen bei der Programmierung, die man durchaus auch nutzen könnte/sollte.
Tipps:
- Vermeide nach Möglichkeit zu lange Ausdrücke mit vielen unterschiedlichen Operatoren. (fasse dich möglichst kurz)
- Vermeide unüberlegte Ausdrücke (man kann sehr oft etwas verbessern, wenn man sich ein wenig Zeit lässt)
- Benutze Klammern, um Übersicht im Ausdruck zu haben und/oder Teile mit niedrigen Operator-Rängen zuerst auswerten zu lassen
Über Operatoren könnte man noch so einiges schreiben, sie sind es auch Wert wie ich finde. Nur soll es hier kein Buch werden und ich habe noch andere Themen, über die geschrieben werden muss(?).