PHPGangsta - Der praktische PHP Blog

PHP Blog von PHPGangsta


Pflichtfelder mit Sternchen markieren via CSS

with 7 comments

Oft möchte man in einem Formular eine Prüfung einbinden, die anschlägt, wenn das Feld nicht gefüllt wurde. Das geht mit dem Zend Framework und Zend_Form sehr einfach:

class Wb_Form_Subscription extends Zend_Form
{
	public function __construct($options = null)
	{
		$element = new Zend_Form_Element_Text('Email');
		$element->setLabel('Email')
				->setRequired(true);
		$this->addElement($element);
	}
}

Mit der setRequired() Funktion fügen wir automatisch eine NotEmpty-Prüfung hinzu, außerdem erhält das Element die CSS-Klasse „required“:

<label for="Email" class="required">Email</label>

Wenn das Formular nun abgeschickt wird und das Feld leer bleibt, erhalten wir eine Fehlermeldung. Diese werden wir nachher noch anpassen. Doch erst möchten wir noch das Feld als Pflichtfeld markieren, mit einem kleinen roten Stern, so wie hier:

required_star

Das können wir auf 3 Arten erledigen, wobei die dritte mein Favorit ist:

$element->setLabel('Email *')
$element->getDecorator('label')->setOption('requiredSuffix', ' * ');

oder via CSS:

.required {
	background-image:url(/img/required-field.png);
	background-position:top right;
	background-repeat:no-repeat;
	padding-right:10px;
}

Eine Beispieldatei kann hier required-field runtergeladen werden.

Achso, die englische Fehlermeldung wollen wir noch anpassen, das geht so:

$element = new Zend_Form_Element_Text('Email');
$element->setLabel('Email')
		->setAttrib('size', 90)
		->setRequired(true)
		->addErrorMessage('Diese Email-Adresse ist ungültig')
		->addValidator('EmailAddress');
$this->addElement($element);

Wenn man für die verschiedenen Validatoren unterschiedliche Fehlermeldungen haben möchte, geht das so:

$element = new Zend_Form_Element_Text('Email');
$element->setLabel('Email')
		->setAttrib('size', 90)
		->setRequired(true)
		->addValidator('NotEmpty', false, array('messages' => 'Leer'))
		->addValidator('EmailAddress', false, array('messages' => 'Ungültig'));
$this->addElement($element);

error_messages

Möchte man nur eine Fehlermeldung haben, muss man den zweiten Parameter ($breakChainOnFailure) auf true setzen. Sobald ein Validator fehlschlägt, wird die Prüfung aller weiteren Validatoren abgebrochen.

Setzt man Zend_Translate ein, sollte man übrigens die Fehlermeldungen mittels Zend_Translate übersetzen lassen, und nicht so wie oben gezeigt. Dazu fügt man einfach eine neue Übersetzung hinzu, mit dem Schlüssel, der sich in den Klassenkonstanten der jeweiligen Validator-Klasse versteckt, wie hier beispielsweise beim EmailAddress-Validator.

Written by Michael Kliewe

Dezember 14th, 2009 at 9:50 am

Posted in PHP

Tagged with , , ,

Virtualisierung: ESXi ausprobieren auf dem Mac

with 3 comments

Wer sich mit Virtualisierung beschäftigt, kommt um VMWare nicht herum. VMWare Workstation haben sicherlich einige von euch schon ausprobiert, sobald es dann aber in Richtung „Server-Virtualisierung“ geht wird die Luft schon dünner.

Wenn man Virtualisierungssoftware (auch Hypervisor genannt) grob unterteilen möchte, gibt es 2 Arten:

  1. Hypervisor, die direkt auf der Hardware laufen („bare metal“, also selbst eine Art Minibetriebssystem) und kein Host-Betriebssystem benötigen. Bekannte Produkte sind hier VMWare ESX, der kostenlose VMWare ESXi, XenServer Hypervisor, Microsofts Hyper-V, Sie werden auch als „Type 1“ oder „Native VM“ bezeichnet.
  2. Applikationen, die auf einem Betriebssystem installiert werden, und dann als Programm gestartet werden. Bekannte Vertreter sind da Sun’s Open Source VirtualBox, VMWare Workstation/Server, Microsoft Virtual PC, KVM, UML, Linux VServer, OpenVZ, Virtuozzo und viele weitere. Sie werden auch als „Type 2“ oder „Hosted VM“ bezeichnet.

In der zweiten Kategorie unterscheidet man dann zwischen „Full Virtualization“ und „Paravirtualization“. Ersteres kann unveränderte Gäste starten, sprich jedes Betriebssystem auf dem Markt, während bei Paravirtualization das Gastbetriebssystem weiß, dass es virtualisiert wird und es angepasst sein muss an diese Situation, es geht also nicht mit jedem Betriebssystem.

Bei den Bare-Metal-Hypervisor gibt es natürlich Hardware-Einschränkungen, da sie direkt auf der Hardware laufen und nicht eine so große Treiber-Unterstützung mitbringen können wie moderne Windows- oder Linux-Betriebssysteme. Daher sollte man sich vorher informieren, ob beispielsweise ESXi auf seiner Hardware überhaupt läuft.

Um etwas mit ESXi zu testen, habe ich mir für zuhause mal einen USB-Stick erstellt mit der ESXi-Software drauf, und davon gebootet. Der Hypervisor bootete auch erfolgreich, jedoch bliebt er beim Laden der USB-Module stecken. Mein Mainboard (ein MSI 790FX GD70) wird also nicht unterstützt. Um trotzdem zu testen, startete ich es in der Firma mal testweise in VMWare Fusion. VMWare Fusion ist quasi das selbe wie VMWare Workstation, nur für Mac. Doch auch hier startete der Hypervisor nicht vernünftig, da ein Hypervisor innerhalb eines Hypervisors nicht unterstützt wird. Doch Dank eines Blog-Artikels habe ich es dennoch ans Laufen bekommen, und nun kann ich ESXi ausgiebig testen.

Ich habe also ein Mac OS X, darauf VMWare Fusion, darin wiederum ESXi installiert, und auf dem ESXi laufen dann weitere Betriebssysteme (aktuell ein Ubuntu 9.10 und Debian Lenny). Damit ich den ESXi administrieren kann, benötigt man VMWare vSphere, welches wiederum nur unter Windows läuft. Also habe ich unter Fusion noch eine Windows Virtual Machine laufen.

Ihr merkt schon, es macht Spass, soviele Betriebssysteme, teilweise verschachtelt, laufen zu lassen 😉

Written by Michael Kliewe

Dezember 10th, 2009 at 5:08 pm

.Net Programmierer hier? Verlosung zu Basta!-Konferenz-Tickets!

with one comment

Die Kollegen von webmasterpro haben mich auf ihre neue Verlosung hingewiesen. Falls sich also ein .Net/C#/Silverlight/Azure – Interessierter hier herumtreibt, sollte er an der Verlosung zu den Tickets teilnehmen. Dazu ist einfach nur ein Kommentar dort zu hinterlassen.

Es gibt volle 3 Tage Konferenzteilnahme in Darmstadt für die 2010 stattfindende Basta! zu gewinnen.

Written by Michael Kliewe

Dezember 3rd, 2009 at 9:00 am

Posted in Allgemein

Tagged with , , , ,

Programmierprinzipien: Law of Demeter

with 14 comments

Professor Ian Holland hat zu Beginn der objektorientierten Zeit (1989) bereits eine wichtige Richtlinie definiert, die die lose Kopplung von Klassen sicherstellen soll: Das „Gesetz von Demeter“ (Law of Demeter, LoD).

Wenn man Klassen soweit es geht voneinander trennt, sind sie übersichtlicher, besser wartbar und testbar, leichter weiterzuentwickeln und wiederzuverwenden. Umgangssprachlich könnte man es beschreiben als „Sprich nur mit deinen nächsten Freunden“ und „Verrate keine Geheimnisse, die andere nichts angehen“.

Ein Praxisbeispiel:

class Order
{
	public $orderStatus = 0;

	public function changeOrderStatus($newStatus, $customer)
	{
		$this->orderStatus = $newStatus;

		if ($newStatus == 3) {
			$this->sendEmail(
					$customer->getData()->getContactInformation()->getEmail(),
					'New Order Status: ' . $newStatus
			);
		}
	}
}

Wer bei diesem Code keine Bauchschmerzen hat, sollte unbedingt weiterlesen. Wenn wir darauf nun die Regeln des LoD loslassen, sehen wir die Probleme.

Eine Klassenmethode sollte nur folgende andere Methoden verwenden:

  • Methoden der eigenen Klasse
  • Methoden der übergebenen Parameter
  • Methoden der mit eigenen Klasse assoziierten Klassen
  • Methoden von Objekten, die die Methode selbst erzeugt hat

Die Zeile 11 wäre also verboten, da sie eine zu enge Kopplung bzw. ein zu großes Wissen über andere Klassen voraussetzt. Lösung wäre hier, nicht das ganze Kundenobjekt an die Methode zu übergeben, sondern nur die für hier wichtigen Kontaktinformationen.

Außerdem verstößt der Code gegen das Geheimnisprinzip, da das Attribut $orderStatus public ist und man so den Status ändern könnte ohne eine Email zu versenden.

Wenn wir einen Test für die oben beschriebene Methode schreiben möchten, müssen wir vorher erst ein Kundenobjekt erzeugen, darin Daten hinterlegen, Kontaktinformationen usw. Doch eigentlich würden die Kontaktinformationen reichen für den Test, das Kundenobjekt ansich ist uns eigentlich egal, da es nicht genutzt wird. Auch Testen wird also durch lose Kopplung einfacher.

Besser wäre z.B. der folgende Code.

class Order
{
	private $_orderStatus = 0;

	public function changeOrderStatus($newStatus, $customerInformation)
	{
		$this->_orderStatus = $newStatus;

		if ($newStatus == 3) {
			$this->_sendEmail(
					$customerInformation->getEmail(),
					'New Order Status: ' . $newStatus
			);
		}
	}
}

Oder man macht es wie im unten stehenden Beispiel. Darin ist auch das Prinzip „Tell don’t ask“ abgebildet, welches besagt, dass man lieber Befehle gibt als Informationen abzufragen:

class Order
{
	private $_orderStatus = 0;

	public function changeOrderStatus($newStatus, $customer)
	{
		$this->_orderStatus = $newStatus;

		if ($newStatus == 3) {
			$customer->sendEmail('New Order Status: ' . $newStatus);
		}
	}
}

Wir geben also dem Kundenobjekt den Befehl, eine Email zu versenden (an den Kunden). Dann ersparen wir uns das Abfragen von Informationen, und wir müssen nicht wissen, wie im Kundenobjekt die Email-Adresse abgespeichert wird. Änderungen der Kundenklasse sind so also viel einfacher und problemloser machbar. Die Klasse Order kümmert sich also hauptsächlich um seine eigenen Dinge, und überlässt alles was den Kunden betrifft wenn es geht der Kundenklasse. Stichwort ist da das Single Responsibility Principle bzw. das  „Eine-Verantwortlichkeit-Prinzip„.

Um nochmal schnell die 4 Prinzipien an Code darzustellen, hier die erlaubten Methodenaufrufe:

Methoden der eigenen Klasse:

class A
{
    public function method1() {
        $this->method2();
    }

    public function method2() {
    }
}

Methoden der Parameter:

class A
{
    public function method1(B $b) {
        $b->method2();
    }
}
class B
{
    public function method2() {
    }
}

Methoden assoziierter Klassen:

class A
{
    private $b;
    public function method1() {
        $this->b->method2();
    }
}
class B
{
    public function method2() {
    }
}

Methoden selbst erzeugter Objekte:

class A
{
    public function method1() {
        $b = new B();
        $b->method2();
    }
}
class B
{
    public function method2() {
    }
}

Weitere Informationen zum LoD gibts im deutschen oder englischen Artikel in der Wikipedia. Oder direkt im Paper des Professors (PDF).

Written by Michael Kliewe

Dezember 2nd, 2009 at 9:02 am

Wave Einladungen für Interessierte

with 16 comments

Ich kann mich noch nicht dazu durchringen, ein umfassendes Urteil über Google Wave abzugeben, aber der erste Eindruck ist sehr ernüchternd. Es kommt mir so vor wie ein webbasierter Messenger, bei dem man mehrere Personen in Räume einladen kann und viel Zeit verbraten kann. Nebenbei noch Dateien tauschen. Nichts was man mit Threaded Emails oder ICQ/Jabber nicht auch machen könnte.

Mag sein, dass da noch mehr ist, oder mittels Gadgets da noch mehr möglich ist, aber bisher hatte ich noch nicht soviel Zeit, es im Detail zu betrachten. Deshalb noch kein ausführlicher Artikel.

Wer sich selbst ein Bild machen möchte, kann hier gern in den Kommentaren einen Pieps sagen, habe noch 7 Einladungen zu verschenken an Interessierte.

wave overview

Written by Michael Kliewe

November 30th, 2009 at 6:31 pm

Posted in Allgemein

Tagged with , ,