NoFollow Free!
SHIFT Weblog

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

Kategorie: Quickies

Datenbanken, Quickies

MySQL: Wochentage auf Deutsch – so gehts

Mit der MySQL-Funktion DATE_FORMAT() gibt es die Möglichkeit, ein Datumsfeld (Typ DATE oder TIME)  formatiert auszugeben. An einigen Stellen habe ich auch die Wochentage des jeweiligen Datums benötigt. Weil diese normalerweise nur auf Englisch ausgegeben werden, könnte man sich PHP-intern mit einem Translation-Array weiterhelfen. Das funktioniert zwar, aber schöner ist es mit diesem Befehl:

SET lc_time_names = 'de_DE'

Nun werden alle Werte in deutsch angegeben, hier zum beispiel in PDO:

$dbh->exec("SET lc_time_names = 'de_DE'");

Man lernt eben nie aus :)

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

PHP, Quickies

How-To: Objekt mit unbekanntem Klassennamen erstellen

Im Bereich der objektorientierten PHP-Entwicklung kann es vorkommen, dass eine unbekannte Klasse aufgerufen werden muss. In einer Factory-Klasse beispielsweise muss man Objekte mit unbekannten Namen und unbekannter Anzahl an Parameter erzeugen.

Ein erster Schritt könnte dieser Versuch sein:

$variable_classname = 'MeineKlasse';
$instanz = new $variable_classname;

Soweit, so gut. Jedoch könnte man Schwierigkeiten haben, wenn dem Konstruktor noch Parameter überladen werden müssen. Da Klassennamen und somit auch die Klassen unterschiedlich sind, könnte jede dieser Klassen eine unbekannte Zahl an Parameter erhalten.

Dann gibt es ja auch noch die Funktion call_user_func_array. Damit könnten wir folgendes anstellen:

$parameter = array('Foo', 'Bar');

$instanz = new MeineKlasse();
call_user_func_array(array('MeineKlasse', '__construct'), $parameter);

Jedoch ist diese Funktion nur sinnvoll, wenn bereits eine Instanz des Objektes besteht. Das bedeutet aber, dass alle erwarteten Konstruktorparameter nur optional sind – und dies ist bei den wenigsten Konstruktoren der Fall. Folgende Idee funktioniert nicht:

$parameter = array('Foo', 'Bar');
call_user_func_array(array(new MeineKlasse, '__construct'), $parameter);

call_user_func_array ist also leider nicht wirklich in der Lage, direkt ein neues Objekt mit unbekannter Parameteranzahl zu erzeugen und dabei den Konstruktor aufzurufen. Was also tun?

Hier findet sich ein nützlicher Einsatz für sogenannte Reflektionsklassen (Reflection Class). Eine Reflektionsklasse könnte als fast untätiges Spiegelbild eines Klassennamens angesehen werden. Und so können wir mit Hilfe einer Reflection Class unser Vorhaben verwirklichen:

$rc = new ReflectionClass('MeineKlasse');
$class = $rc->newInstanceArgs(array('Foo', 'Bar'));

echo $class->tuIrgendwas();

CSS, Quickies

Formularelemente mit gleicher Höhe – so geht’s

Submit Button auf gleicher Höhe

Ich hatte heute (mal wieder) das Problem, dass in einem Formular der Submit-Button aus der Reihe getanzt ist, was die per CSS definierte Höhe betraf.

Weiterlesen ›