Archiv für den Monat: Juni 2011

Fatal Error im neuen Zend Framework Projekt

Ich setze grad eine neues Zend Framework Projekt im Zend Studio auf, vergebe Namen und Ort, Zend Studio macht auch einiges und *plop* ein neues Projekt ist geboren.

Zend Server und hosts noch einstellen und ein kleiner Test im Browser sagt mir: „Ja, alles okay, Projekt kann starten!“

Aber schon nach den ersten paar Zeilen im index Controller gehts los:

Fatal error: Cannot redeclare class zend_loader. If this code worked without the Zend Optimizer+, please set zend_optimizerplus.dups_fix=1 in your php.ini in C:\zend\Apache2\htdocs\blahblah\library\Zend\Loader\PluginLoader.php on line 27

Nach langem Suchen: Die Lösung findet sich in der /public/index.php, dort diese Zeilen auskommentieren:

// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
realpath(APPLICATION_PATH . '/../library'),
get_include_path(),
)));

Dann funktionieren auch wieder alle Aufrufe 😉

Method-Chaining in eigenen PHP-Projekten einsetzen

Klassen und Objekte kennt ja nun mittlerweile fast jeder, ein PHP-Framework wie ZendFramework oder CodeIgniter haben sich sicherlich auch schon viele zumindest mal angesehen … will ich hoffen. Nun, auch wenn man die Frameworks nicht direkt einsetzt, so kann man doch viel von ihnen lernen. Viele der Techniken, die in bekannten PHP-Frameworks eingesetzt werden, entstanden entweder aus dem großen Ästhetischen Faible, den nun mar jeder Entwickler hat oder schlicht aus Faulheit der Programmierer 😉

Egal, eines der – wie ich finde – tollen Features in vielen Frameworks ist die Möglichkeit, mehrere Funktionen eines Objektes hintereinander aufrufen zu können, ja, es sieht schon fast wie ein normaler Satz aus, was dann im Editor steht und seinen Dienst verrichtet. Diese Möglichkeit der sog. “Fluent Interfaces” nennt man “Method-Chaining” (und wieder im Bullshot-Bingo gewonnen, *strike*).

Kleines Beispiel, kennen wir alle, unsere Basisklasse:

class Base1 {
function macheEins() {
// some magic here
}
function macheZwei($parameter) {
// more magic here
}
}

Das ganze rufe ich nun auf:

$myBaseClass = new Base1();
$result1 = $myBaseClass->macheEins();
$result2 = $myBaseClass->macheZwei($result1);

Was passiert? Das Ergebnis des Aufrufs von “macheEins” ist der Parameter für “macheZwei”. Das ganze sieht strukturiert aus und ist lesbar, was also soll man besser machen können? Nein! Bitte jetzt nicht sagen, man könne doch sowas machen:

$myBaseClass = new Base1();
$result2 = $myBaseClass->macheZwei($myBaseClass->macheEins());

Sicher, es funktioniert, aber: NEIN! Macht das nicht! Warum? Ganz einfach: Debugge das mal, viel Spaß. Denn wenn man erst einmal mit so einem falschen Verhalten anfängt, dann verschachteln sich schnell auch mal 5 oder 8 Funktionen ineinander und finde dann mal den Fehler, viel Spaß! Also: Ganz klares “So nicht!”.

Aber wie dann?

Zunächst müssen uns im klaren sein, was die Klasse macht. Offenbar braucht “macheZwei” ein Ergebnis einer Berechnung einer anderen Funktion der Klasse. Dieses Ergebnis könnte man doch genauso innerhalb der Klasse speichern und dann benutzen.

class Base2 {
private $valueHolder;
function macheEins() {
$this->valueHolder = someMagic;
return $this->valueHolder;
}
function macheZwei() {
return $this->valueHolder * someMoreMagic;
}
}

Schon erfüllt die Klasse auch die Anforderungen, aber … so richtig “fluent” will das ganze nicht werden, obwohl ja nun im Aufruf von “macheZwei” der Übergabeparameter fehlt. Was nun? Und wie sieht denn so ein “Fluent Interface” mit “Method-Chaining” nun aus? Der Aufruf sähe in unserem Beispiel in etwa so aus:

$myBaseClass = new BaseFluent();
$result2 = $myBaseClass->macheEins()->macheZwei();

Aber unsere derzeitige Klasse unterstützt das nicht! Wie bekommen wir unsere Klasse nun “Fluent”?

Nun, dazu müssen wir diese massiv umbauen. Der größte Umbau ist, dass die einzelnen Methoden nicht mehr direkt die Ergebnisse liefern, sondern “nur” das Objekt selbst zurückgeben … und darin liegt auch schon der ganze Trick. Den Methodenaufruf kann ich immer nur auf einem Objekt machen. Eine Methode, die mir einen Basisdatentypen zurück liefert, kann ich dafür nicht gebrauchen, da ich auf diesem Basistypen (int, String, array, …) keine weiteren Methoden meiner Klasse aufrufen kann.

Nehmen wir mal an, im letzten Code stünde statt “new BaseFluent” ein “new Base2”. Dann würde der Aufruf:

$result2 = $myBaseClass->macheEins()->macheZwei();

folgendes bedeuten: Rufe die Methode “macheEins” auf dem Objekt “myBaseClass” auf, diese gibt den Datentyp von valueHolder zurück (nehmen wir mal an, es wäre ein integer mit dem rein zufälligen Wert 42), rufe dann auf dem Objekt 42 die Methode “macheZwei” auf … *meep* Fehlermeldung, “42” ist kein Objekt, hat daher generell keine Methoden und erst recht keine spezielle Methode mit dem Namen “macheZwei” also Fehler und Script Abbruch.

Der Trick besteht nun darin, dass die Methoden des Objektes nicht mehr die eigentlichen Ergebnisse zurückgeben, sondern das Objekt der Klasse selbst; darauf darf man ja dann auch wieder Methoden derselben Klasse aufrufen, also bauen wir flugs die Klasse um:

class BaseFluent {
private $valueHolder;
function macheEins() {
$this->valueHolder = someMagic;
return $this;
}
function macheZwei() {
$this->valueHolder *= someMoreMagic;
return $this;
}
function getValueHolder() {
return $this->valueHolder;
}
}

Man erkennt nun, wohin die Reise geht. Getter und Setter werden implementiert, um die Daten zu holen, die Methoden geben uns $this zurück, worauf wir weiterhin Klassenmethoden aufrufen können und wir haben nun unser “Fluent Interface” für “Method-Chaining” in PHP realisiert; war doch gar nicht schwer und hat auch gar nicht weh getan, oder?

In der freien Wildbahn trefft ihr auf diese Art des Codens übrigens ganz stark beim ZendFramework an, bei CodeIgniter geht es wohl auch, denke ich (ich mache mich da erst seit kurzem fit und bitte alle CI-Fans, meine Unwissenheit zu entschuldigen). Es macht aber auch Spaß, dass bei eigenen Klassen umzusetzen, die sowieso umgearbeitet werden sollen. Sieht einfach viel übersichtlicher aus. Und noch ein Tipp: Mehr als zwei Verkettungen sollten untereinander stehen, also so:


$myBaseClass->macheEins()
->macheZwei()
->macheDrei()
->undNochMehr();

Viel Erfolg damit …

10 Regeln für Entwickler

Es gibt viele „Regeln“ zum Programmieren, viele „Goldene Regeln“; das hier sind meine.

  1. Glaube nicht, wisse!
    Glauben heißt, nicht zu wissen. Sei kein Gläubiger, sei ein Wissender! Hebe dich von der Schar derer ab, die nur Oberflächliches kennen, jene, die nur auswendig lernen, was in den „xyz for dummies“ Büchern steht. Du bist anders, du bist smart: Du verstehst, was da steht!
     
  2. „Know your Enemy“
    ”Kenne deinen Feind”; lerne Sachen, die du hasst; verdamme nicht einfach Dinge, die neu oder anders sind: Lerne Sie, verstehe, warum diese Dinge so sind, warum ein Autor das auf diese Weise gelöst hat und wieso nicht anders. Verinnerliche neues, sei bereit für die Änderung, wiege alle Optionen ab: Und dann nimm die am besten passende!
     
  3. Notepad? Benutz eine IDE!
    Benutze eine IDE; Lerne die Features “deiner” IDE kennen und nutze diese Gnadenlos aus! Verstehe, dass jeder „seine“ IDE braucht und das keine IDE wirklich besser ist als eine andere: Es kommt nur auf den Entwickler an, der den Code schreibt!
     
  4. Benutze Standards
    Standards wurden von schlauen Menschen entwickelt, damit diese auch mit Code zurecht kommen, den weniger schlaue Hacker schrieben; du benutzt deinen eigenen Standard nicht, weil du ein guter Entwickler bist; Du benutzt deinen eigenen Stil, weil du die Standards bisher nicht verstanden hast! (siehe 1,2)
     
  5. Object to go
    Klassen erleichtern dir das Leben: Sie lösen eine Aufgabe und das machen Sie effizient; ist die Klasse gut, macht Sie das sogar auf einer abstrakten Ebene und du kannst die Klasse nicht nur für dieses Problem einsetzen, sondern für alle ähnlichen Probleme. Aus (1) erkennst du, wie toll das ist, du nimmst die Klasse mit und bist fast am Ziel. Klassen und Objekte sind dein Freund: Benutze Sie auch!
      
  6. Kommentiere weise
    Kommentiere deine Funktionen, deine Klassen, eine extrem schwer zu verstehende Stelle im Code oder eine Stelle, in der du mal von der internen Norm abweichen musstest; Kommentiere nichts triviales; Kommentiere keine Kommentare -> das ist Code, kein Chat!
     
  7. Hacke nicht, komponiere
    Programmier kann jeder, wahrhaft entwickeln ist eine Kunst. Die richtige Wahl der Werkzeuge, das Arrangement der Funktionen, die Sitzordnung des Frameworks, die kurze Ruhe vor dem Beginn des Deployments … Du programmierst nicht, du komponierst Code und diese Kunst kann keiner Würdigen … außer ein anderer Codeponist.
     
  8. Bleib auf dem Teppich
    Ja, du bist der tollste Coder der Welt, aber keiner nimmt es zur Kenntnis? Liegt daran, dass keiner deinen Code lesen kann. Lesbarkeit ist wichtig, vor allem für dich selbst. Lies dich mal nach 12 Monaten und 4 Zwischenprojekten wieder in deinen „hochoptimierten“, „perfekten“ und „commentless“ Code ein … und dann weißt du, dass du (3),(4),(5) und (6) nicht verstanden hast. Sechs, setzen … Anfänger!
     
  9. Teile und herrsche
    Wussten schon die Römer, nur du weisst es wieder nicht. Teile dein Wissen, denn wenn du nicht fähig bist zu lehren, dann hast du es nicht richtig verstanden (siehe 1 und 2). Bringe dein Team auf deinen Wissenstand und messe dich regelmäßig mit stärkeren, mit schlaueren, mit „Wissenden“ … denn nur im direkten „Code-Wettkampf“, sei es nun mündlich oder als Code-Kata, kannst du erst über dich hinaus wachsen, deine Schwächen erkennen (und die hast du, glaube mir) und damit erst bist du in der Lage, dich zu verbessern. Wisse, dass du nichts weist; Plato wusste das auch … und du lernst das auch noch vom Kollegen nebenan!
     
  10. Don’t Panic
    Die wichtigste Regel und ich hoffe, ich muss dazu nichts mehr sagen!
Dies sind meine Regeln,
es gibt viele Regeln, aber diese sind meine…
Wie sehen deine aus???