31. Januar 2012 | 5 Comments Im Heutigen Beitrag geht es nicht um „Design Patterns in der Praxis“ sondern um die Vorstellung eines Frameworks – mit den Design Patterns geht es nächste Woche weiter. Thema Heute ist das Kohana Framework in der aktuellen Version 3.2.0. Kohana ist ein sogenanntes Full Stack HMVC Framework mit vielen Modulen und einer Gesamtgröße von etwa 1MB (ohne Dokumentationen und Tests). Full Stack bedeutet, das ihr keine weiteren Bibliotheken oder sonstigen Tools benötigt um eine funktionierende Web-Applikation zu erstellen. Von Haus aus gehört eine komplexe Datenbank-Abstraktion, ein Objekt-Relationaler Mapper, ein kaskadierendes Dateisystem, sowie ein Routing und mehr als 20 Helfer-Klassen dazu. Bevor ich mich nun aber auf die einzelnen Themen stürze möchte ich erklären was überhaupt ein HMVC Framework macht… MVC Frameworks basieren auf dem „Model View Controller“-Pattern. Das ist ein Entwurfsmuster um die drei Elementaren Bestandteile einer (Web-)Applikation voneinander zu trennen: Model – Ein Model wird in der Software-Entwicklung zur Datenbeschaffung und -verarbeitung benutzt. Grob gesagt geht es hier um Datei- und Datenbankzugriffe. View – Eine View wird benutzt um Inhalte darzustellen. In diesem Fall handelt es sich um HTML Templates, mit denen wir unsere Applikation im Browser darstellen. Controller – In diesem Bereich wird die „Logik“ untergebracht. Der Controller behandelt die Daten aus dem Model, bereitet sie auf und stellt sie mit Hilfe der View dar. Das „H“ im HMVC steht für „Hierarchical“ (bzw. „Hierarchisch“) – Ein besonderes Feature, welches uns erlaubt innerhalb eines Requests weitere Requests abzusetzen (welche wiederum eigene Requests abschicken können usw.). Das ganze lässt sich am einfachsten mit Ajax vergleichen – Nur eben Serverseitig 😉 Wenn ich mich richtig erinnere hatte sich Kohana ursprünglich aus dem CodeIgniter (CI) Framework entwickelt. Während CI auf PHP4 basierte hatte sich das Kohana Team der Umsetzung auf PHP5 gewidmet – Das ist allerdings schon einig Zeit her (Damals noch Kohana 2.0). Mit Kohana 3.0 wurde das Framework dann von Grund auf neu gebaut. In meinen letzten Postings hatte ich bereits einige Male kleine Codeschnipsel gezeigt, die aus dem Kohana Framework stammen – Heute möchte ich etwas genauer auf die verschiedenen Features eingehen! Datenbank-Abstraktion Kohana bringt eine relativ umfangreiche Datenbank-Abstraktion mit, mit deren Hilfe sich SQL-Queries mit einem sogenannten „Query-Builder“ erstellen lassen. Diesen Query-Builder hatte ich bereits in älteren Beiträgen gezeigt (SQL-Injection vorbeugen und Design Patterns in der Praxis – Teil 4). Das ganze ist durch die Nutzung des Fluent-Interface Patterns sehr leserlich gehalten und bietet außerdem eine grundlegende Filterung von Daten (außer man nutzt DB::expr() zum einfügen von Inhalten). // Ein Beispiel des Kohana Query-Builders. $query = DB::select() ->from('posting') ->where('created_at', '<', DB::expr('NOW()')) // Direktes SQL, welches nicht gefiltert wird. ->limit(5) ->order_by('inserted_at', 'DESC'); ORM Anfangs empfand ich das ORM als etwas lästig und habe den Zweck nicht verstanden, doch sobald ich erkannte worum es hier geht wollte ich es am liebsten für alles Mögliche einsetzen. Das ORM liefert für jeden Datensatz ein Objekt zurück und ist darüber hinaus noch in der Lage Beziehungen zwischen Tabellen/Feldern abzubilden. Nachdem eine ORM-Model Klasse einmalig angelegt und grob konfiguriert wurde lässt sich folgendermaßen damit arbeiten: // Ein Beispiel des Kohana ORM Systems. $postings = ORM::factory('posting') ->where('id', '=', $posting_id) // Es lassen sich Methoden aus dem Query-Builder nutzen. ->limit(5) ->find_all(); foreach ($postings as $posting) { /* * Eine Beziehung zu einer anderen Tabelle (hier "author") muss * einmalig in der Model-Klasse konfiguriert werden, danach kann man sehr komfortabel * auf die hinterlegten Daten zugreifen. */ echo $posting->titel . '<br />' . 'Geschrieben von ' . $posting->author->name . '<br />' . $posting->text; } Greift man auf eine Beziehung zu, erhält man ein vollwertiges ORM-Objekt welches wiederum mit Methoden aus dem Query-Builder arbeitet. // Beispielhafte Nutzung von Beziehungen innerhalb des ORM. $authors = ORM::factory('authors')->find_all(); foreach ($authors as $author) { // Dieses mal greifen wir vom Author aus auf alle seine Postings zu. $postings = $author->posting->where('created_at', '<', DB::expr('NOW()'))->find_all(); foreach ($postings as $posting) /// ... Aber Achtung! Da jede erhaltene „Zeile“ ein eigenes Objekt ist, sollte das ORM System nicht für große abfragen genutzt werden (laut einem Eintrag im Kohana-Forum alles über 10 000 Zeilen). Ich selbst habe meinen alten Blog mit dem ORM System betrieben und kam (selbst bei etwa 60 Einträgen pro Seite) nie über 4MB (Arbeits-) Speicherauslastung. Kaskadierendes Dateisystem Zugegeben, mit diesem Begriff konnte ich anfangs nicht viel anfangen, doch es ist schnell erklärt: Kohana verfügt über drei Ordner in der obersten Ebene: application, modules und system. Wird nun Beispielsweise versucht eine Klasse zu instanziieren so wird zuerst in application danach gesucht. Konnte sie nicht gefunden werden, werden die aktivierten Module innerhalb von modules durchsucht. Wurde auch hier nichts gefunden landet man im system Ordner – Ist auch hier nichts zu finden wird eine Exception geworfen. Der Vorteil dieses ganzen Vorgehens ist: Ihr könnt theoretisch alle Modul- und Systemklassen überschreiben und in eurem application Ordner ablegen. Dadurch habt ihr keinerlei Framework Code verändert und könnt (in der Regel) problemlos updaten wenn eine neue Version zum Download bereit steht! Super Sache! Routing Als abschließendes Feature möchte ich kurz das Routing erläutern. Kohana bietet euch die Möglichkeit von Anfang an mit „sauberen“ URLs zu arbeiten – Das heißt, ihr habt keine URLs die so aussehen: http://leonardfischer.de/?seite=ueber_mich http://leonardfischer.de/?seite=aktuelles&posting=123 Sondern SEO-Konforme (leserliche) URLs wie z.B. http://leonardfischer.de/ueber-mich http://leonardfischer.de/aktuelles/posting-123 Das definieren solcher Routen ist relativ einfach und dennoch ziemlich dynamisch (dank Regex): // So würden die beiden URLs von oben als definierte Routen aussehen: // Parameter: "Name der Route", "Muster", "Muster-definition" (Optional, mit Hilfe von Regex-Regeln) Route::set('content-seite', '(<seite>)', array('seite' => '[\w-]+')) ->defaults(array( 'controller' => 'content', // Definiert den zu nutzenden Controller 'action' => 'load' // Definiert die zu nutzende Action (standard "index") )); Route::set('posting-seite', 'aktuelles/posting-<id>', array('id' => '[\d]+')) ->defaults(array( 'controller' => 'content', 'action' => 'posting' )); Dabei gibt es ein paar Syntax-Regeln zu beachten: Der Name der Route ist frei wählbar und wird zur dynamischen Link-Generierung benötigt: // Aus Routen lassen sich Links generieren. Route::url('posting-seite', array('id' => 123); // Würde "/aktuelles/posting-123" zurückliefern. Die Route selbst lässt sich folgendermaßen definieren: Runde Klammern machen einen Teil der URL optional (siehe erstes Beispiel – Der „seite“ Parameter ist in der URL optional). Spitze Klammern („<“ und „>“) definieren einen bereich, der sich von Regex näher definieren und im Controller verwenden lässt: // Innerhalb einer Action eines Controllers... Request::$current->param('seite'); // Würde beim ersten Beispiel "ueber-mich" zurückliefern. Passt keine Route zur eingegeben URL wird eine 404-Exception geworfen (welche sich fangen und entsprechend als „404-Seite“ darstellen lässt). Ich vermute einige der vorgestellten Features lassen sich erst wirklich verstehen wenn man sich Kohana mal selbst aufsetzt und etwas damit spielt und rumprobiert. Ich kann es nur empfehlen und freue mich über Rückmeldungen und Kommentare gleichermaßen! Für Heute möchte ich hier aber Schluss machen – Es gibt zwar noch viel zu erzählen, doch das passt nicht alles in einen einzigen Beitrag. Vielleicht werde ich in den nächsten Wochen eine Art „Teil 2“ veröffentlichen. Euch da draußen noch eine angenehme Arbeitswoche!
Ich möchte wieder in PHP einsteigen. Kohana gefällt mir bisher von allen FWs am Besten. Was sind die größten Nachteile? Was würdest Du sagen? Ich möchte nicht mitten in einem Projekt feststellen, dass Kohana totaler Schrott ist.. 😉 Antworten
Hi Simon, das kommt sicherlich darauf an wofür du Kohana einsetzen möchtest. Als Nachteil ist mir bisher nur aufgefallen das es etwas aufwändig ist wenn man rundum cachen möchte – Da haben Frameworks wie symfony2 klar die Nase vorn – Dort passiert das nämlich alles irgendwie „von selbst“… Allerdings meine ich etwas über das HTTP Caching bei Kohana 3.3 (dessen RC1 Vorgestern vorgestellt wurde) gelesen zu haben! Ich wollte mich da ohnehin noch mal drüber informieren… Ich könnte für nächste Woche ja den angesprochenen „Teil 2“ dieses Eintrags fertig schreiben! Das würde natürlich gut zum neuen Release des Frameworks passen 🙂 Antworten
Hallo, schöne Einführung. Gibt es eigentlich irgendwo ein Beispielprojekt, um mal nicht nur Code-Schnipsel zu sehen, sondern auch das Gesamtkonzept dahinter zu verstehen? Danke und Gruß Moritz Antworten
Hallo Moritz, die Dokumentation von Kohana ist ja leider nicht die beste – Doch dafür gibt es z.B. Projekte wie „kohanajobs“ ( http://www.kohanajobs.com/ ) als komplettes Paket auf github ( https://github.com/GeertDD/kohanajobs ) zum durchstöbern und runterladen. Ich bin mir leider nicht sicher, auf welcher Kohana-Version das Projekt basiert… Doch es sollte mehrere solcher Beispielseiten geben. Viele Grüße, Leo Antworten