Archiv der Kategorie: CodeIgniter

No input file specified.

Codeigniter kann einen in den Wahnsinn treiben mit dieser Meldung:

No input file specified.

Sonst nix.

Hier für alle, vor allem für mich, der „fix“ dazu:
In der .htaccess hinter dem „index.php“ aber noch vor dem „/“ ein „?“:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]

Zumindest bei meinen Projekten funktioniert dann wieder alles wie es soll.

Codeigniter Logo

Codeigniter’s letztes Query im Active Record

Codeigniter’s letztes Active Record Query wird mit

$result->last_query()

abgerufen, nicht Zend Framework like

$result->lastQuery()

Codeigniter-Hint: redirect auf Startseite

Codeigniters redirect auf die Startseite mit Statuscode 301 ohne berücksichtigung der Dateiendung funktioniert nicht mit

redirect('/', 'location', 301);

sondern mit

redirect('', 'location', 301);

Damit wird auf die Homepage umgeleitet, ohne dass die Voreingestellte Dateiendung berücksichtigt wird!

$_GET in Codeigniter nutzen

Ganz kurz: Bei Codeigniter auf URL-Parameter mit $_GET zugreifen:


parse_str(substr($_SERVER['REQUEST_URI'],strpos($_SERVER['REQUEST_URI'],'?')+1,strlen($_SERVER['REQUEST_URI'])-strpos($_SERVER['REQUEST_URI'],'?')),$_GET);

Dann kann auch $_GET benutzt werden

Das Framework updaten

Wer kennt das nicht? Man betreut eine Vielzahl unterschiedlicher Projekte. Im Idealfall betreut man nur wenige und kennt diese fast auswendig … aber wer von uns lebt schon im Idealfall? Eben …

So ein PHP-Projekt ist eine komplizierte Sache und auch die „kleinen“ bestehen aus einer Vielzahl unterschiedlicher Technologien. Zum einen (meist) ein Framework als Basis, sei es das Zend Framework oder Symphony oder CakePHP oder CodeIgniter oder oder oder, dann – bei den neueren und „cooleren“ Projekten – eine Datenbankabtraktionsschicht (ich kenne das z.B. Doctrine, aber es gibt da auch ein paar mehr) und dann kommt die Schicht Code, die uns dann die grauen Haare machen, die Anwendungsschicht, so nenne ich nun mal den Teil des Codes, den man bei einem Projekt mit Framework-Basis selbst schreibt.

Nach vielen Tagen ist der Code fertig, alle Tests zeigen „Grün“, das Deployment war (außnahmsweise mal) angenehm einfach und alles ist perfekt. Der Kunde ist zufrieden, der Zeit- und Projektplan eingehalten, der Chef spendiert ne Pizza und nach vielen Wochen hat man endlich mal wieder einen der wenigen „Geschafft“-Momente, die einem wieder Rückenwind geben. Toll.

Nach ein paar Wochen kommt dann aber schon die erste Verbesserung, der erste Bugfix, der erste neue Kundenwunsch. Die perfekte Anwendung muss aktualisiert werden. Im Bereich der Anwendungsschicht meist ein leichtes. Käfer erschlagen, Feature eincoden, Test, VCS, Deploy, „der nächste bitte“; das war einfach.

Allerdings kommt es irgendwann und du kannst dich nicht davor verstecken. „You can run, but you can’t hide!“ (gibt es so ein YCRBYCH-Prinzip eigentlich irgendwo? Ich habe da nichts finden können.). Das Framework, die Basis der Anwendung wird (meist von extern) aktualisiert. Und nun?

Meistens hält man sich ja auf dem Laufenden und schaut nach, was es denn neues gibt. „Ah ja, Aha, soso, benutzen wir ja gar nicht, brauchen wir nicht updaten.“ Okay, kann passieren, aber, wie schon gesagt, YCRBYCH – das Changelog zeigt nun sehr viele Änderungen, Bugfixes, Performance-Improvements usw. genau in den Klassen und Bereichen an, die in der Kundenanwendung benutzt werden. Und nun der Worst-Case: Bugfixes zu Exploits sind auch dabei. Es heißt also: Das Framework updaten!

Und nun? Nun, sicher, Framework auf dem lokalen System updaten, testen, Testsystem updaten, testen usw. Aber eines musst du zugeben: Du hast ein mulmiges Gefühl dabei! Es könnte was schiefgehen. Klar, eigentlich kann nichts schiefgehen, aber es könnte doch sein … und dann?

An dem Punkt dachte ich dann über folgendes nach: Warum können wir mit einem Framework nicht machen, was ein Browser heute schon kann (und andere Software eigentlich auch können sollte): Silent-Update! Also, ein Update installieren ohne dass was schiefgeht? Ganz einfach: Weil dann etwas schiefgehen wird, Murphy’s Law, kennt jeder.

Nach tausend „ja, aber…“ Gedanken machte es dann bei mir *klick* (ich möchte jetzt keinen „Schnellmerker“ Kommentar hören!) … sowas wie „Silent-Updates“ machen wir doch … nur eben nicht wir Entwickler bei uns selbst, sondern wir Entwickler beim Kunden. Sobald die Anwendung getestet und für gut befunden ist wird diese meist auch deployed (und ich hoffe mal, dass die Anwendung dann immer noch funktioniert) und dies in der Regel ohne das der Kunden nochmal dazu extra ein „Ja, updaten“ Knopf drücken muss.

Aber kann man einen PHP-Code nicht auch so schreiben, dass man das zugrunde liegende Framework jederzeit gegen eine neuere Version eintauschen könnte? Ich setze vorraus, dass keine Architektonischen Änderungen am Framework vorgenommen werden, dass also das Framework „manual-compatible“ ist. Wie ist deine Meinung dazu? Wie müsste der Code dazu aussehen? Kann man solchen Code überhaupt schreiben? Oder ist das Utopie?

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 …