NoFollow Free!
SHIFT Weblog

Dieses Blog ist ein Online-Magazin für erfahrene Website-Entwickler und Webdesigner, die PHP und Webdesign lieben.

Kategorie: PHP

PHP

Mein Verständnis von MVC

mvc_v

MVC – diese drei Buchstaben haben es in sich. MVC ist ein Design Pattern, eine strukturelle Lösung für Entwickler. Kaum ein anderes Design Pattern löst so viel Kontroverse aus und regt zu endlosen Diskussionen an – zumindest in der PHP-Welt.

Das liegt daran, dass MVC recht oberflächlich beschrieben wird, und möchte man sämtliche MVC-Erklärungsversuche zusammenfassen, so ist man schnell der Auffassung:

  • Model (M) : Die Verbindung zur Datenbank
  • View (V) : Die Ausgabe an den Benutzer
  • Controller (C) : Der Verwalter zwischen den Schichten

Die Wahrheit ist aber: Es ist viel mehr als das. Der große Fehler, den MVC-Neulinge dabei begehen, ist, ihr Projekt nur nach diesen Gesichtspunkten zu gestalten. Oft wird übersehen, dass MVC nur eines von mehreren Zahnrädern in einer ganz anderen Schichtenarchitektur ist: Der Präsentationsschicht, der Logikschicht (auch als Businessschicht bezeichnet) und der Persistenzschicht. MVC agiert in allen drei Schichten, hauptsächlich jedoch in der Präsentationsschicht. Verfolgt man MVC-Diskussionen in gängigen Foren, kommt erschwerend hinzu, dass jeder MVC etwas anders auslegt. Es gibt also nicht selten kein “richtig” oder “falsch”. Die Grenzen, die MVC versucht aufzuzeigen, scheinen paradoxerweise ineinander zu verschwimmen.

Ich versuche, mit diesem Artikel dem Verständnis von MVC auf die Sprünge zu helfen, ich betone aber, dass dies nur meine Auffassung des Patterns ist. Ich möchte daher nicht deutlich machen, dass meine Ansicht die richtige oder die falsche ist – es ist eher ein mögliches Konzept zur strukturellen Realisierung von MVC. Außerdem liefere ich hier kein MVC-Tutorial, die allgemeine Funktion des Patterns sollte bekannt sein.

Weiterlesen ›

PHP

Ausnahmezustand: PHP und Exceptions

Exit

Mit PHP 5 wurde dem Entwickler ein Werkzeug zur Verfügung gestellt, dass es in anderen objektorientierten Sprachen wie C++ und Python schon lange gibt: Exceptions. Mit diesen hat der Entwickler die Möglichkeit, auf ungewollte Ereignisse zu reagieren. Exceptions werden “geworfen”, das bedeutet, sie unterbrechen den normalen Programmfluss und behandeln eine eventuelle Ausnahme, die den weiteren Programmverlauf stören können. In einer Desktopapplikation beispielsweise könnten Exceptions genutzt werden, um noch vor dem Windows-Fehlermeldungsfenster ein eigenes zu generieren, in der der Benutzer die Möglichkeit hat, einen Fehlerbericht an die Softwarefirma zu schicken. Ohne diese Ausnahmebehandlung würde das Programm mit einer Windows-Standardmeldung sang- und klanglos abstürzen und der User wäre verwirrt. Auch in PHP lassen sich Exceptions sinnvoll nutzen. Mit Exceptions sind sicherlich schon einmal alle Entwickler in Berührung gekommen, die ein MySQL-Statement via PDO mit einer fehlerhaften Syntax abgegeben haben.

Im unten aufgeführten Beispiel mal ein ganz einfacher Anwendungsfall – zunächst ohne Fehlerbehandlung: Aus einer Zahl soll eine Wurzel gezogen werden:

$a = sqrt(9); // Wert von $a: 3
$b = sqrt(-9); // Wert von $a: NaN

Weiterlesen ›

PHP, Quickies

Snippet: Geldbeträge mit PHP bereinigen

Folgendes Szenario: Ein Benutzer einer PHP-Applikation muss einen Geldbetrag eingeben. Für die Weiterberechnung und Speicherung dieses Betrages erwartet PHP ein Format wie 123 oder 567.89, nicht aber 246,80 oder 500,-.

Bevor dem Benutzer der Applikation lange Erklärungen geben, wie eine solche Eingabe auszusehen hat, sollten wir uns selbst um die Bereinigung der Geldbetrageingabe kümmern. Wenn der Benutzer allerdings wirklich Quatsch eingibt (etwa ‘foo,bar’) so sollte ein Wert von 0 bzw. 0.00 zurückgegeben werden.

Weiterlesen ›

PHP, Webdesign

This is not sexy: PHP-Template-Engines á la Smarty

Smarty not sexy

Nachdem ich mich in der Vergangenheit über das Zend Framework, Flash und CSS Frameworks ausgelassen habe, ist es mal wieder an der Zeit, den Buhmann zu spielen und möchte mich hier nun über einige PHP-Template-Engines aussprechen. Stellvertretend für viele dieser Projekte werde ich im laufe des Artikels “Smarty” nennen – ich glaube, dass dieser Name vielen PHP-Entwicklern ein Begriff ist.

Der Grundgedanke ist nicht verkehrt: Bei der Erstellung von (PHP-)Applikationen sollte darauf geachtet werden, die Programmlogik vom Design und der Ausgabe zu trennen. Unter Beachtung der Model-View-Controller-Struktur sollte dieses Vorhaben auch keine Hexerei sein. Doch wie könnte man den PHP-Code vom Design (der XHTML-Datei) trennen? Ganz einfach: Mit einer Template-Engine. Sie kümmert sich um die Zuweisung von Variablen innerhalb des Controllers und um die Ausgabe der in der View-Datei. Eine simple View-Datei unter Beachtung des MVC-Prinzips könnte nun also so aussehen:

<!DOCTYPE html>
<html>
    <head>
        <title><?php echo $titel; ?></title>
    </head>
    <body>
        <h1>Hallo <?php $username; ?></h1>

        <?php echo $usercontent; ?>
    </body>
</html>

Doch Halt! Eigentlich wollten wir doch den PHP-Code vom Design trennen, oder? In unserer View-Datei ist nun aber trotzdem PHP-Code zu sehen. Was können wir tun, damit der Designer nicht am, *räusper*, hochsensiblen PHP-Code werkeln muss? PHP-Template-Engines wie Smarty verwenden für die Lösung des Problems eine Metasprache, die auch ohne PHP-Code die Ausgabe und Formatierung von Variablen übernimmt.

Weiterlesen ›

PHP, Quickies

Snippet: Praktische E-Mail-Validierung

E-Mail-Validierung (C) OmirOnia

Nicht selten muss innerhalb eines PHP-Projektes die Gültigkeit einer E-Mail-Adresse verifiziert werden. Mit älteren PHP-Version half hier oft ein Regulärer Ausdruck (Regex) aus, mittlerweile steht uns PHP-Entwicklern aber die (oftmals) praktische Funktion filter_var zur Verfügung. Die Benutzung dieser Funktion im Falle der E-Mail-Validierung sieht wie folgt aus:

var_dump(filter_var('admin@mysite.org', FILTER_VALIDATE_EMAIL) !== false);; // ergibt bool(true)
var_dump(filter_var('notexist.org', FILTER_VALIDATE_EMAIL) !== false);; // ergibt bool(false)

Dies funktioniert eigentlich hervorragend, wäre da nicht der kleine, aber feine Unterschied bei der Gültigkeit von E-Mail-Adressen. Laut offiziellem Standard ist nämlich auch so eine E-Mail-Adresse valide:

admin@localhost
test@wurstbrot (und so weiter...)

Im Praxisfall ist so eine Art von E-Mail natürlich nutzlos – das wage ich jetzt einfach mal zu behaupten. Für solche Fälle habe ich eine kleine Funktion erstellt, die eine String als E-Mail-Adresse verifiziert. Dabei wird auch gleichzeitig geprüft, ob die Domain existiert – das macht Eintragungen wie asdasdasd@asdasdasd.asd obsolet.

Und hier ist sie:

function validateMail($email, $checkdns = true) {
    if(preg_match("/^[a-zA-Z0-9_.-]+@[a-zA-Z0-9][a-zA-Z0-9-.]+\.([a-zA-Z]{2,6})$/" , $email) && filter_var($email, FILTER_VALIDATE_EMAIL) !== false ) {
        $tmp = explode('@', $email);
        $domain = $tmp[1];
        if($checkdns && @dns_get_record($domain) === false) {
           return false;
        }
    } else {
        return false;
    }
    return true;
}

Hier eine kurze Erläuterung: Zuerst wird die Adresse anhand eines regulären Ausdrucks geprüft (wie in alten Zeiten) und, um sicherzustellen, wird auch die filter_var-Funktion zu Rate gezogen. Das wäre eigentlich überflüssig, allerdings ist es möglich, dass mein regulärer Ausdruck nicht ganz perfekt ist und hole mir so sicherheit durch die PHP-interne Funktion.
Danach wird die Domain aus der E-Mail-Adresse extrahiert und auf Existenz geprüft, sofern der zweite Parameter der Funktion nicht auf false gesetzt wurde.

Noch eine kleine Anmerkung bezüglich der unterdrückten Fehlermeldung in Zeile 3: dns_get_record gibt nicht einfach nur false zurück, wenn die Domain nicht existiert – es meldet sich dann in diesem Falle lautstark mit einer Notice, was wir natürlich nicht möchten. Ansonsten sollte man natürlich tunlichst auf so eine Praxis vermeiden, jedoch geht es hier nicht anders.

Schlägt eine der Prüfungen fehl, so gibt die Funktion false zurück, andernfalls (wie könnte es auch ander sein) true.

Achtung…

Ich benutze diese Funktion sehr gerne, allerdings gibt es hier eine kleine Stolperfalle: Mittlerweile existieren bekanntlich sogenannte Umlaut-Domains, beispielsweise www.günstige-schöne-mähdrescher.de – die filter_var- und die dns_get_record-Funktion lehen Umlaute aber strikt ab, weshalb auch meine Funktion die E-Mail-Adresse nicht verifiziert.

Als “Workaround” könnte man hier noch eine Prüfung auf vorhandene Umlaute implementieren. Wenn dies der Fall ist, findet keine DNS-Prüfung statt und ein leicht veränderter regulärer Ausdruck wird zur Prüfung angewandt.

function validateMail($email, $checkdns = true, $consider_umlauts = true) {
    if(preg_match('/^[a-zA-Z0-9_.-]+@[a-zA-Z0-9][a-zA-Z0-9-.]+\.([a-zA-Z]{2,6})$/' , $email) && filter_var($email, FILTER_VALIDATE_EMAIL) !== false ) {
        $tmp = explode('@', $email);
        $domain = $tmp[1];
        if($checkdns && @dns_get_record($domain) === false) {
           return false;
        }
    } elseif($consider_umlauts && preg_match('/^[a-zA-Z0-9äöüÄÖÜ_.-]+@[a-zA-Z0-9äöüÄÖÜ][a-zA-Z0-9-äöüÄÖÜ.]+\.([a-zA-Z]{2,6})$/', $email)) {
        // Workaround for german Umlauts
        return true;
    } else {
        return false;
    }
    return true;
}

Testlauf

So, und jetzt wollen wir doch einmal die Funktion testen:

$testArray = array(
    'test@test.de',
    'mailaddress@googlemail.com',
    'test.test.test',
    'a@b.c',
    'admin@localhost',
    'user@äöüäöü.de', //DNS Prüfung wird ignoriert
    'mail@umlaut.dä', //DNS Prüfung wird ignoriert
    'asdf@asdfasdasd.asd',
    '@.de'
);

foreach($testArray as $email) {
    echo $email . ':<br />';
    var_dump(validateMail($email, true, false));
    echo '<br /><br />';
}

Hier die Ausgabe:

test@test.de:
bool(true)
mailaddress@googlemail.com:
bool(true)
test.test.test:
bool(false)
a@b.c:
bool(false)
admin@localhost:
bool(false)
user@äöüäöü.de:
bool(false)
mail@umlaut.dä:
bool(false)
asdf@asdfasdasd.asd:
bool(false)
@.de:
bool(false)