Mein eigenes MVC-Framework – Verzeichnisstruktur und __autoload()

<< Zurück zur Übersicht

Der Grundgedanke

Ein wichtiges Kriterium bei der Entwicklung meines Frameworks ist die Wiederverwendbarkeit. Um mehrere Projekte mit nur einem FW betreiben zu können, habe ich mir folgendes überlegt:

Alles, was nur für das Framework benötigt wird, befindet sich ein einem eigenen Ordner. Jedes Projekt erhält einen eigenen Ordner und initiiert das Framework mit einem einzigen include-Befehl.

Jedes Projekt hat eigene Konfigurationsmöglichkeiten. Am Frameworkordner selbst muss in den meisten Fällen nichts geändert werden.

Welche Verzeichnisse und Dateien werden benötigt?

Wir brauchen auf jeden Fall ein Verzeichnis, das den Zugriff per HTTP erlaubt. Idealerweise zeigt die Domain auf dieses Verzeichnis.

/projektname/www

In diesem Tutorial heisst es “www”. (/projektname/www)

In /projektname/www gibt es nur 2 Dateien:

  • .htaccess für unsere (optionalen) RewriteRules
  • index.php

Projektname steht natürlich für das aktuelle Projekt. Wenn später Bilder oder Cascading Style Sheets (CSS) benötigt werden, kommen diese auch in dieses Verzeichnis!

/projektname/classes

Hier kommt die gesamte Logik des Projekts hinein: Controller, Models, Filter, SubController, ViewHelper und mehr. Was das im einzelnen ist, wird in einem späteren Kapitel noch geklärt. Lasst euch von Filter, SubController und ViewHelper nicht verwirren!

/projektname/config

Hier liegen unsere Konfigurationsdateien, die aber nicht zwingend nötig sind. Alles kann auch direkt über PHP-Code konfiguriert werden. Ich finde es aber einfacher, wenn man alles über eine Datei verwalten kann und nicht ewig im Code suchen muss.

/projektname/logs

PHP braucht schreibrechte auf diesen Ordner. Hier werden Fehler geloggt.

/projektname/viewfiles

Hier gibt es 3 Unterordner:

  • layouts (Seitenlayouts)
  • templates (normale Templates)
  • static_templates (Templates, die ihren Inhalt nicht ändern)

/framework

Alles, was das Framework angeht, wird hier gespeichert. Wichtig ist, dass NICHTS projektabhängiges hier rein kommt. Unter anderem befindet sich die Bootstrap-Datei (base_config.php) hier. Sie muss von jedem Projekt includet werden, falls das Framework dort zum Einsatz kommen soll.

/framework/classes

Wichtige Klassen wie der Frontcontroller oder der Debugger sind hier zu finden. Es ist eigentlich das wichtigste Verzeichnis. Für den korrekten Betrieb sollte hier nichts verändert werden (müssen). Sonst liegt wohl ein Konzeptfehler vor.

/framework/base_config.php

Die wahrscheinlich wichtigste Datei von allen ist die base_config.php.  Sie belegt die Config-Klasse mit Standartwerten und registriert unseren Autoloader. Obwohl die Datei mit ihren 6 Zeilen nicht lang ist, erledigt sie doch sehr viel.

/ (root)

Das Root-Verzeichnis beinhaltet nur die Projektordner und den Framework-Ordner.

Es sieht also so aus:

  • /
    • /projekt1
      • /www
        • index.php
        • .htaccess
      • /classes
        • /Controller
        • /SubController
        • /Model
        • /Filter
        • /ViewHelper
      • /config (optional, wird aber empfohlen)

        • config.ini (optional)
        • db.ini (optional)
        • config.php (optional)
      • /logs
      • /viewfiles
        • /layouts
        • /static_templates
        • /templates
      • autoload.php (optional, wird aber empfohlen)
    • /projekt2, /projekt3, … (gleiche Stuktur wie oben)
      • /framework
        • base_config.php
        • /classes

    Autoload macht uns die Arbeit einfacher

    Es gibt seit PHP5 eine Funktion namens __autoload() (2 Unterstriche!). Das ist eine sogenannte Interzeptormethode (magische Methode). Sie wird aufgerufen, wenn eine undefinierte Klasse angefordert wird.

    Da in diesem Framework so gut wie alles mit OOP gelöst wird, betrifft das auch die __autoload()-Funktion. Sie wird nicht direkt über “function __autoload($class)” definiert, sondern über spl_autoload_register. Das hat den großen Vorteil, dass es mehrere Autoloader geben kann, welche sich alle in einem Stack (Stapel) bedinden und nacheinander ausgeführt werden, bis die entsprechende Datei gefunden wurde.

    Es gibt eine statische Methode zum Registrieren des Autoloaders in /framework/classes/Autoload.class.php. Diese sieht so aus:

    /**
       * @access public
       * @param mixed autoloader
       *
       * registriert einen weiteren autoloader
       */
      public static function register($autoloader = null)
      {
        if($autoloader === null)
        {
          spl_autoload_register(array('FW_Autoload', 'load'));
        }
        else
        {
          spl_autoload_register($autoloader);
        }
      }

    Wenn kein Parameter an die Methode übergeben wird, wird der Standartautoloader registriert.
    Er befindet sich in der selben Klasse wie die register-Methode. Unsere Autoload-Funktion ist so aufgebaut:

    /**
       * @access public
       * @param string classname
       *
       * Diese statische Methode lädt eine Klasse, wenn sie benötigt wird.
       * Sie findet nur Klassen, die mit FW_ beginnen.
       * --> Ist der Autoloader fürs FW
       */
      public static function load($className)
      {
        if(substr($className, 0,3) == "FW_") //nur wenn die Klasse zum FW gehört
        {
          $classFile = FW_Config::getInstance()->get("fw_class_path")."/".str_replace("_", "/", substr($className, 3)).".class.php";
          if(file_exists($classFile))
          {
           require_once($classFile);
          }
        }
      }
    

    FW_Autoload::load($className) erwartet ein Argument ($className – der Name der Klasse).
    Nur wenn die Klasse mit “FW_” anfängt, wird nach der Klasse gesucht. Wenn ein Klassenname einen Unterstrich enthält (der von FW_ zählt nicht), representiert dieser einen Verzeichniswechsel:

    FW_Irgend_Was wird in /irgend/was.class.php gesucht.

    Aber wo wird der Autoloader registriert? Und woher kommt FW_Config? Die erste Frage wird im nächsten Abschnitt geklärt. Die zweite hier ;)

    FW_Config ist eine Klasse nach dem Singleton-Pattern. Sie speichert ALLE wichtigen Daten rund um das Projekt bzw. das Framework. Wie man sie mit Daten füttert, erfahrt ihr noch später. Wir wollen ja nichts überstürzen.

    base_config.php

    Bevor ich große Erklärungen schreibe, poste ich hier den Inhalt:

    /**
     * @licence See: /licence.txt
     */ 
    
    /**
     * @author Simon Hessner
     * @package MVC-Framework
     * @version 1
     *
     * Diese Klasse muss von jedem Projekt, das das Framework verwendet, includet
     * werden. Dadurch wird der Autoloader aktiviert und die wichtigsten Ein-
     * stellungen vorgenommen.
     */ 
    
    require_once('classes/Autoload.class.php');
    require_once('classes/Config.class.php');
    $config = FW_Config::getInstance();
    $config->set("fw_path", dirname(__FILE__));
    $config->set("fw_class_path", $config->get("fw_path")."/classes");
    FW_Autoload::register();
    

    In den ersten beiden Zeilen werden die Klassen für den Autoloader und die Konfiguration geladen.
    Danach wird eine Instanz von FW_Config erzeugt und mit Daten gefüttert.
    Als letztes muss nur noch der Autoloader registriert werden.

    Anhang: Die fertige Autoload-Klasse
    Hier kommt noch die komplette Autoload-Klasse für euch:

    /**
     * @licence See: /licence.txt
     */ 
    
    /**
     * Klasse dient als Container für 2 statische Methoden und wird nie instanziert.
     * @package MVC-Framework
     * @version 1
     * @author Simon Hessner
     *
     * FW_Autload ist eine Klasse, die verwendet wird, um einen Autoloader zu registrieren.
     */
    class FW_Autoload
    {
      /**
       * @access public
       * @param string classname
       *
       * Diese statische Methode lädt eine Klasse, wenn sie benötigt wird.
       * Sie findet nur Klassen, die mit FW_ beginnen.
       * --> Ist der Autoloader fürs FW
       */
      public static function load($className)
      {
        if(substr($className, 0,3) == "FW_") //nur wenn die Klasse zum FW gehört
        {
          $classFile = FW_Config::getInstance()->get("fw_class_path")."/".str_replace("_", "/", substr($className, 3)).".class.php";
          if(file_exists($classFile))
          {
           require_once($classFile);
          }
        }
      }
    
      /**
       * Singleton-Elemente: private __construct
       *                     private __clone
       */
      private function __construct() {} //verhindern, dass new verwendet wird
      private function __clone() {} //verhindern, dass durch Kopieren 2 Objekte entstehen
    
      /**
       * @access public static
       * @param mixed autoloader
       *
       * registriert einen weiteren autoloader
       */
      public static function register($autoloader = null)
      {
        if($autoloader === null)
        {
          spl_autoload_register(array('FW_Autoload', 'load'));
        }
        else
        {
          spl_autoload_register($autoloader);
        }
      }
    }
    

    Weiter geht’s
    Im nächsten Kapitel wird der FrontController programmiert. Der FrontController routet die Anfragen von Clients und lädt den Controller.
    Weiter zum FrontController

    Keine verwandten Beiträge gefunden.

    1 Star2 Stars3 Stars4 Stars5 Stars (2 Stimme, durchschnittlich 5.00 / 5)
    Loading ... Loading ...

    Dieser Artikel wurde von Simon verfasst.
    Gelesen: 7243x heute: 4x

    Dieser Artikel wurde am Sonntag, August 17th, 2008 um 15:46 in den Kategorien Mein MVC-Framework geschrieben. Du kannst die Kommentare über den Feed (RSS 2.0) beobachten. Du kannst eine Antwort hinterlassen, oder einen Trackback von deiner Seite setzen.


    6 Kommentare zu “Mein eigenes MVC-Framework – Verzeichnisstruktur und __autoload()”

    1. [...] Tricks für Webmaster PHP, MySQL, HTML, JavaScript, AJAX, usw… « Java-Zitat Mein eigenes MVC-Framwork – Verzeichnisstruktur [...]

    2. [...] Die Verzeichnisstruktur [...]

    3. [...] Mein eigenes MVC-Framework – Verzeichnisstruktur und __autoload() [...]

    4. [...] Mein eigenes MVC-Framework – Verzeichnisstruktur und __autoload() (50) [...]

    5. [...] Mein eigenes MVC-Framework – Verzeichnisstruktur und __autoload() (456) [...]

    6. [...] [...]

    Hinterlasse einen Kommentar!

    CommentLuv Enabled

    Nein, mich gibt es nicht bei Twitter!

    »Archiv

    Easy-Profit.info
    Angebote und Einkaufen klimaneutral -  bei kaufDA.de Browser-Statistiken
    Dieser Blog ist gehostet bei ALL-INKL.COM - Webhosting Server Hosting Domain Provider