Servus,

es gibt noch so viele Funktionen die PHP dir bietet und die ich dir zeigen möchte - ich finde aber dass das alles mehr Sinn ergibt wenn du verstehen lernst, was Funktionen überhaupt sind. Fangen wir also heute damit an.

<h3>Was sind Funktionen?</h3>

Du hast schon einige Funktionen kennengelernt wie z.B. substr() oder rand(), an den entsprechenden Stellen habe ich versprochen dass ich dir bald zeige was Funktionen sind - heute ist es soweit.

Funktionen sind speziell separierte Code-Teile die über einen von dir festgelegten Namen aufgerufen werden können. In eine Funktion kannst du beliebigen Code schreiben und bei Bedarf kannst du noch Daten an die Funktion übergeben (eine Funktion kann Parameter haben und an die werden Argumente übergeben). Es kommt in eher seltenen Fällen vor dass an eine Funktion keine Daten übergeben werden, meist brauchst du das also.

Standardmäßig schreibst du Funktionen so dass sie einen Rückgabewert liefern (mit dem Schlüsselwort return). Das muss nicht immer sein aber meist macht es mehr Sinn es zu tun - kommt wie immer ganz drauf an was du vor hast.

Schauen wir das für unser erstes Beispiel ohne Rückgabewert an.

<h3>Wie wird eine Funktion deklariert?</h3>

Das ist einfach, du deklarierst die Funktion nach dem Schlüsselwort function mit einem von dir beliebig festgelegten Namen. Anschließend folgen Klammern (zwischen denen erst mal nix steht). Die geschweiften Klammern legen dann den Bereich fest innerhalb dessen du deinen Code schreibst.

Einfaches Beispiel:

<pre class="lang:default decode:true " title="Funktion deklarieren und aufrufen">&lt;?php # Funktion deklarieren function meine_funktion() { echo "Hallo Welt!"; } # Die Funktion aufrufen meine_funktion(); // Gibt "Hallo Welt!" aus ?&gt;</pre>

Du siehst, wir haben eine Funktion meine_funktion() und die rufen wir unten auf - weil wir keine Daten an die Funktion übergeben müssen da die beiden Klammern hin ohne was dazwischen - mehr dazu weiter unten. Das macht vorerst mal wenig Sinn denn das würde ohne Funktion 1) viel einfacher und 2) mit viel weniger Code genauso gut funktionieren. Dennoch zeigt es die grundsätzliche Funktionsweise und wie man es nutzen kann.

<h3>Funktion mit Rückgabewert</h3>

Mir ist klar dass du noch immer nicht recht weiß was das Ganze mit dieser Funktionen-Geschichte soll, aber bleib am Ball, der Sinn erschließt sich dir in wenigen Minuten.

Wie oben angemerkt ist eine Funktion hauptsächlich dazu da um (mit return) einen Wert zurückzugeben. Versuchen wir das mal anhand eines Beispiels, indem wir einen zufälligen Tag der Woche durch die Funktion getRandomDayOfWeek() zurückgeben:

<pre class="lang:default decode:true " title="Funktion um zufälligen Tag der Woche zurückzugeben">&lt;?php # Funktion deklarieren function getRandomDayOfWeek() { $Days = [ 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag', ]; # Gibt aus dem $Days Array einen zufälligen Eintrag zurück # (Also zwischen 0 und Anzahl-Einträge minus 1, somit zwischen 0 und 6) return $Days[rand(0, count($Days) - 1)]; } # Einen zufälligen Wochentag ausgeben echo getRandomDayOfWeek(); ?&gt;</pre>

Kurs nacheinander was da alles passiert:

  1. Funktion getRandomDayOfWeek() wird deklariert
  2. Innerhalb der Funktion erstellen wir ein Array mit Wochentagen
  3. Mit dem Schlüsselwort return geben wir einen zufälligen Eintrag aus dem Array zurück.
  4. Mit echo geben wir den Wert der durch die Funktion geliefert wird im Browser aus.

Als Ergebnis siehst du im Browser einen der 7 Wochentage.

Du musst das nicht gleich ausgeben sondern kannst den Wert der durch die Funktion zurückgeliefert wird auch in eine Variable speichern. Kurzes Beispiel (ich verzichte darauf die Funktion überflüssigerweise nochmal zu deklarieren):

<pre class="lang:default decode:true ">&lt;?php # Den Rückgabewert in eine Variable speichern $DayOfWeek = getRandomDayOfWeek(); echo "Ein zufälliger Wochentag könnte " . $DayOfWeek . " sein."; ?&gt;</pre>

Hier ist im Ansatz schon ein Vorteil erkennbar den Funktionen dir bieten, nämlich dass Code einmal geschrieben wird und an vielen Stellen wiederverwendet werden kann.

<h3>Passwortgenerator-Beispiel</h3>

Du erinnerst dich an das Beispiel mit dem Passwortgenerator aus dem letzten Beitrag? Gut, das packen wir jetzt in eine Funktion - am Code selbst ändern wir nichts außer dass wir das Passwort in der Variable $Passwort mit return zurückgeben.

<pre class="lang:default decode:true">&lt;?php function getRandomPassword() { # Das Passwort kann folgende Zeichen enthalten $Zeichen = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789?%!$"; # Die Passwortlänge festlegen $Laenge = 8; # $Passwort wird nachher das Passwort enthalten $Passwort = ""; # Eine Schleife von 0 bis 7 (sind dann also 8 Durchläufe - somit 8 Zeichen Länge) for ($i = 0; $i &lt; $Laenge; $i++) { $Zufallszeichen = substr($Zeichen, rand(0, strlen($Zeichen) - 1), 1); $Passwort .= $Zufallszeichen; } # Hier geben wir das generierte Passwort zurück: return $Passwort; } # Das Passwort ausgeben: echo getRandomPassword(); ?&gt;</pre>

Die Ausgabe kann etwas sein wie "jEv?9DaV" oder "9B8AQRjC" oder ähnliches.

So, jetzt siehst du erst mal wie geil es ist Funktionen zu haben. Ohne eine Funktion müsstest du den Code der in der Funktion steht (das sind ja schon einige Zeilen Code zu tippen) an jeder Stelle neu schreiben wo du ihn benötigst um ein Zufallspasswort zu generieren. Bei Funktionen hingegen schreibst du die Logik für einen Prozess nur einmal und rufst ihn später über den Namen der Funktion einfach nur noch auf. Was für geile Scheiße ist das denn! :)

Gehen wir einen Schritt weiter und machen den Passwortgenerator NOCH besser. Hierzu bedienen wir uns der Möglichkeit von Funktionsparametern (oder Funktionsargumenten - benutze das Wort das dir besser gefällt).

<h3>Funktionen mit Parametern</h3>

Von außen haben wir bisher keine Möglichkeit, das was in der Funktion passiert irgendwie zu beeinflussen. Zu diesem Zweck können wir an eine Funktion Daten übergeben (Argumente) und der Code in der Funktion kann diese Daten verwenden und mit ihnen arbeiten.

Fangen wir damit an dass wir an die Funktion die Länge des zufällig zu generierenden Passworts übergeben - ein Passwort das immer nur 8 Zeichen lang ist ist schön, aber viel cooler wäre es doch wenn wir selbst bestimmen könnten wie lang das Passwort werden soll.

Bevor wir das machen zeige ich dir zuerst noch ein paar kurze und kleine Beispiele damit du siehst wie das mit der Übergabe von Daten die die Funktion überhaupt funktioniert.

Ich hab hier eine Funktion addieren() und -du siehst es in den Klammern nach dem Funktionsnamen- die erwartet 2 Argumente. Dementsprechend musst (ja, musst, geht nicht anders) du beim Aufruf der Funktion auch zwei Werte übergeben. Welche das sind ist egal, allerdings solltest du beim Aufruf zumindest wissen welcher Datentyp von der Funktion erwartet wird. Aber schau erst mal:

<pre class="lang:default decode:true">&lt;?php # Eine Funktion zum Addieren von 2 Zahlen function addiere($zahl1, $zahl2) { return ($zahl1 + $zahl2); } # Addieren echo addiere(5, 4); // Gibt "9" aus ?&gt;</pre>

Zwischen den beiden Klammern nach dem Funktionsnamen (die bisher nutzlos erschienen) können übrigens beliebig viele Parameter festgelegt werden - in diesem Beispiel haben wir zwei davon.

Relativ klar und auch am Funktionsnamen schon erkennbar ist, dass hier offensichtlich Zahlen übergeben werden sollen. Typehinting behandeln wir in einem späteren Beitrag noch ganz detailliert, deshalb genügt das was wir an dieser Stelle haben, auch ganz ohne aufwendige Validierung und sonstigem Krempel.

Aber ich schweife ab - zurück zu den Daten die übergeben werden. Die Funktion arbeitet auch hier wieder einen ganz bestimmten und vordefinierten Prozess ab. Hier beispielsweise werden 2 Zahlen addiert - ziemlich simpel. Beim Aufruf müssen dann entsprechend reale Werte übergeben werden - in eben diesem Beispiel ist es irrelevant aber grundsätzlich ist es natürlich sehr wichtig dass die Werte logisch in der gleichen Reihenfolge übergeben werden wie die Funktion es vorgibt.

<h3>Optionale Parameter</h3>

Im vorherigen Beispiel legen wir fest dass beim Aufruf an die Funktion exakt 2 Werte übergeben werden müssen. Ein Versuch die Funktion addiere() ohne Werte, mit nur einem Wert oder mit mehr als 2 Werten aufzurufen wird scheitern - probier's aus. Es müssen dort 2 Werte sein die übergeben werden.

Du kannst Parameter in Funktionen auch als optional definieren indem du ihnen bei der Deklaration direkt einen Wert zuweist - das heißt für diesen Parameter muss nichts übergeben werden, kann aber.

Nehmen wir als Beispiel eine kleine Funktion um aus einem Preis schnell den Netto-Betrag zu ermitteln (du kaufst ja im Laden zu Brutto-Preisen wo die Mehrwertsteuer schon enthalten ist). Dazu lege ich als 1. Parameter den Preis fest und optional als 2. Parameter noch den Mehrwertsteuersatz (derzeit 19%) der beim Aufruf der Funktion übergeben werden kann, aber nicht muss.

<pre class="lang:default decode:true">&lt;?php # Eine Funktion zum Berechnen des Nettopreises function getNetto($bruttopreis, $mwst = 19) { # Hier die "komplexe" Rechenoperation return round(($bruttopreis / (100 + $mwst) * 100), 2); } # Netto berechnen # Nettopreis von 4,99€ berechnen # (mit den 19% weil wir selbst keinen eigenen Mehrwertsteuersatz übergeben) echo getNetto(4.99) . "&amp;euro;"; echo "&lt;br&gt;"; // Zeilenumbruch # Nettopreis mit 16% MwSt. ausrechnen (das waren noch Zeiten ...) echo getNetto(4.99, 16) . "&amp;euro;"; ?&gt;</pre>

Du siehst, beim ersten Aufruf übergeben wir nur den Bruttopreis (der muss übergeben werden) und die MwSt legen wir nicht fest. Die Funktion verwendet in dem Fall wenn nichts übergeben wurde den Wert den der Parameter bereits zugewiesen bekommen hat, also 19.

Beim zweiten Aufruf übergeben wir unseren eigenen gewünschten Mehrwertsteuersatz von 16% - die Funktion nimmt dann nicht die 19 sondern die 16.

Ganz wichtig ist, dass optionale Parameter (nach dem Funktionsnamen in den Klammern) immer erst nach den Pflichtparametern angegeben werden. Du kannst also nicht eine Funktion deklarieren die zuerst einen optionalen Parameter hat und als zweites dann einen Pflicht-Parameter - denk kurz drüber nach dann merkst du selbst dass das logischerweise totaler Stumpfsinn ist.

<pre class="lang:default decode:true ">&lt;?php # Das funktioniert function irgendwas($param1, $param2 = "optional") { /* ... */ } # Das funktioniert NICHT function wasanderes($param1 = "optional", $param2) { /* ... */ } ?&gt;</pre>

Natürlich ist es abgesehen davon aber möglich dass eine Funktion gar keine Parameter hat oder nur aus optionalen Parametern besteht.

<h3>Die supercoole Passwortgenerator-Funktion</h3>

So, jetzt geht's zurück zum ursprünglichen Beispiel. Unsere Passwortgenerator-Funktion erhält zwei optionale Parameter und zwar

  1. für die Länge des Passworts (standardmäßig 8 Zeichen lang)

  2. für die Zeichen die im Passwort vorkommen sollen (standardmäßig Klein- und Großbuchstaben sowie Zahlen und ein paar Sonderzeichen).

Bedeutet also dass wir mehrere Möglichkeiten haben diese Funktion aufzurufen:

  1. ganz ohne Daten zu übergeben oder
  2. wir können nur einen Wert übergeben oder
  3. wir können zwei Werte übergeben

Dementsprechend beeinflussen wir was die Funktion genau für uns tut.

Legen wir los:

<pre class="lang:default decode:true">&lt;?php # Die Funktion hat 2 Parameter von denen beide optional sind. # Beide Parameter haben einen Standardwert. Wenn wir beim Aufruf der # Funktion nichts übergeben werden diese Standardwerte im Code genutzt. # Wir können auch für die Länge oder für beide Parameter eigene Werte übergeben. function getRandomPassword($Laenge = 8, $Zeichen = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789?%!$") { # $Passwort wird nachher das Passwort enthalten $Passwort = ""; # Eine Schleife von 0 bis 7 (sind dann also 8 Durchläufe - somit 8 Zeichen Länge) for ($i = 0; $i &lt; $Laenge; $i++) { $Zufallszeichen = substr($Zeichen, mt_rand(0, strlen($Zeichen) - 1), 1); $Passwort .= $Zufallszeichen; } # Hier geben wir das generierte Passwort zurück: return $Passwort; } # Passwort mit Standardwerten generieren # Die Werte werden von der Funktion vorgegeben weil wir keine # eigenen übergeben. echo getRandomPassword(); echo "&lt;br&gt;"; # Ein kurzes Passwort # Wir übergeben die Passwortlänge. Aus welchen Zeichen das Passwort # besteht gibt die Funktion vor. echo getRandomPassword(4); echo "&lt;br&gt;"; # Ein längeres Passwort # Das gleiche wie eben nochmal. echo getRandomPassword(20); echo "&lt;br&gt;"; # Ein 10-Zeichen langes Passwort bestehend aus den übergebenen Buchstaben und Zahlen # Wir überschreiben die Standardwerte der Parameter mit unseren eigenen Werten. echo getRandomPassword(10, "xy123"); echo "&lt;br&gt;"; # Ein Passwort bestehend nur aus Zahlen # Auch hier legen wir Länge und Zeichen selbst fest. echo getRandomPassword(20, "0123456789"); ?&gt;</pre>

BAM!

Ziemlich nice, die übergebenen Werte nehmen Einfluss darauf was die Funktion zurückgibt.

<h3>Ein Wort zum Geltungsbereich (<em>"Scope"</em>)</h3>

Wichtig zu wissen ist, dass Variablen die außerhalb einer Funktion deklariert wurden innerhalb einer Funktion nicht genutzt werden können. Ebenso können Variablen die in einer Funktion deklariert wurden außerhalb nicht verwendet werden.

Ein Beispiel:

<pre class="lang:default decode:true ">&lt;?php # Variable die im "globalen" Scope deklariert wurde $Variable = "Wert"; function irgendwas() { # Das klappt nicht echo $Variable; # Variable die in einer Funktion deklariert wurde $VariableInFunktion = 123; } # Das klappt auch nicht echo $VariableInFunktion; ?&gt;</pre>

Dieser "Geltungsbereich" oder "Scope" legt quasi die Erreichbarkeit fest. Der globale Scope ist immer dort wo irgendein PHP-Code steht der sich nicht in einer Funktion befindet (und nicht in Klassen oder Namespaces usw. aber dazu kommen wir später mal). Im Grund spielte sich alles was wir in den vorherigen Artikeln geschrieben haben im globalen Scope ab

<pre class="lang:default decode:true">&lt;?php # Das hier ist der globale Scope function irgendwas(){ # Das hier ist der function scope. # Was hier passiert bleibt hier drin } # Das hier ist der globale scope ?&gt;</pre>

Eine Funktion schafft wieder einen eigenen Scope, d.h. ein abgekapselter Bereich in dem alles was dort geschrieben wird keinerlei Auswirkung hat auf den Rest (den globalen Scope oder andere Funktionen (oder Klassen etc..)).

Das gilt übrigens nicht für Konstanten die mit define deklariert wurden - die sind unabhängig vom Scope überall gültig und zugreifbar. Konstanten sind "superglobal" ebenso wie die Variablen $_GET, $_POST, $_SERVER oder $_SESSION und noch ein paar andere. Das heißt auf die kann immer und von überall aus zugegriffen werden.

Schau:

<pre class="lang:default decode:true ">&lt;?php # Kontante deklarieren define('KONSTANTE', 'Irgendein Wert'); # Eine Funktion function irgendwas(){ # Konstante ausgeben echo KONSTANTE; } # Funktion aufrufen irgendwas(); ?&gt;</pre>

Schlüsselwort global

Mit dem global Schlüsselwort kann man innerhalb einer Funktion auf Variablen aus dem globalen Scope zugreifen:

<pre class="lang:default decode:true ">&lt;?php # Variable die im globalen Scope deklariert ist $Variable = "Wert"; function irgendwas(){ # Mit global eine Variable in den aktuellen scope importieren global $Variable; echo $Variable; } # Funktion aufrufen irgendwas(); ?&gt;</pre>

Die Ausgabe im Browser ist Wert .

Werte als Referenz an eine Funktion übergeben

Als letztes -und damit sind wir auch am Ende des Artikels angelangt- schauen wir uns noch an wie wir Werte als Referenz an eine Funktion übergeben. Bisher war es so dass wir an Funktionen mit Parametern die Werte als Kopie übergeben haben. Die eigentliche Variable wurde nicht verändert, wie folgendes Beispiel zeigt:

<pre class="lang:default decode:true ">&lt;?php function irgendwas($param) { $param = 123; } # Eine Variable deklarieren $Variable = "Wert"; # Funktion aufrufen und $Variable übergeben irgendwas($Variable); # $Variable ausgeben: echo $Variable; ?&gt;</pre>

Die Ausgabe im Browser ist "Wert". Zwar haben wir $Variable an die Funktion übergeben und dort wurde der Wert geändert, allerdings haben wir nur eine Kopie von $Variable übergeben, was den eigentlichen Wert nicht verändert.

Anders verhält es sich wenn eine Variable als Referenz übergeben wird, was bedeutet dass wir dann tatsächlich die Variable und ihren Wert dorthin übergeben und verändern können. Dazu fügen wir vor den Parameter das &-Zeichen hinzu. Ändern wir also im Code dieses eine Zeichen und schauen uns das nochmal an:

<pre class="lang:default decode:true ">&lt;?php # Jetzt mit &amp;$param was heißt dass die Variable als Referenz übergeben wird. function irgendwas(&amp;$param) { $param = 123; } # Eine Variable deklarieren $Variable = "Wert"; # Funktion aufrufen und $Variable übergeben irgendwas($Variable); # $Variable ausgeben: echo $Variable; ?&gt;</pre>

Wie du siehst ist in Zeile 4 der Parameter jetzt um das &-Zeichen erweitert. Die Ausgabe im Browser ist nun "123".

<h4>Tipps zu best practice code</h4>

global: Wenn du gern sauber programmierst rate ich dir davon ab, global zu benutzen. Das hat man früher gemacht und findet man auch heute noch vor, allerdings nur in Webapplikationen die eine schlechte Struktur aufweisen und vermutlich keine Klassenstrukturen verwenden. Gewöhn' dir das am besten nicht an.

<h3>Zusammenfassung</h3>

<ul> <li>Funktionen werden mit dem Schlüsselwort function deklariert, über den Funktionsnamen erfolgt später der Aufruf</li> <li>Funktionen können Parameter haben um Werte zu übergeben und somit den Programmfluss zu steuern. Einer Funktion mit Parametern <strong>müssen</strong> beim Aufruf Werte übergeben werden, kommagetrennt also exakt soviele Werte wie die Funktion Parameter erwartet.</li> <li>Eine Funktion kann optionale Parameter haben, indem man den Parametern direkt in der Funktion gleich Werte zuweist. Man kann ihnen beim Aufruf Werte übergeben, wenn man keine übergibt werden die Standardwerte genutzt.</li> <li>Wenn eine Funktion Pflichtparameter <em>und</em> optionale Parameter nutzt, <strong>müssen</strong> die optionalen Parameter immer rechts von den Pflichtparametern stehen.</li> <li>Eine Funktion bildet einen eigenen Scope. Variablen die außerhalb von Funktion deklariert wurden können innerhalb der Funktion nicht genutzt werden und umgekehrt.</li> <li>Mit dem Schlüsselwort global können wir Variablen aus dem globalen Scope in Funktionen nutzen. Funktioniert, ist aber "schlechter Stil".</li> <li>Variablen die an Funktionen übergeben werden, können dort nicht verändert werden (wir übergeben nur den Wert der Variable, nicht die Variable selbst. Anders verhält es sich bei der Übergabe als Referenz, indem man dem Parameter ein &amp;-Zeichen voranstellt. Hierbei wird dann die Variable direkt übergeben und kann manipuliert werden.</li> </ul>

<h3>Fazit</h3>

Wie du siehst sind Funktionen wahnsinnig praktisch um Code auszulagern und die Funktionalität ohne den Code jedes mal neu schreiben zu müssen einfach über einen Funktionsaufruf zu nutzen. Ein weiterer Vorteil ist, dass dein Code damit auch besser strukturiert ist.

Apropos Struktur, damit machen wir im nächsten Artikel weiter, indem ich dir zeige wie du Code in mehrere Dateien auslagern kannst und sie mit nur einer Zeile importierst. Du kannst nicht für immer damit weitermachen eine komplette Webanwendung in nur eine Datei zu schreiben, das wird schnell unübersichtlich und schwer wartbar.

Grüße Marius