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 H.
 * @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 H.
 * 
 * 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

1 Star2 Stars3 Stars4 Stars5 Stars (7 Stimme, durchschnittlich 4,14 / 5)
Loading...


9 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. […] […]

  7. Vielen Dank Entsendung von dem Artikel seiner sehr Gott.
    Sie so viel für die Buchung Ihrer inspirierenden Geschichten. Es muss schwer gewesen sein, damit Sie diese mit uns teilen, aber hoffentlich mehr Menschen ihren Traum vom Schreiben, oder zumindest, was einem zu gehen und niemals aufzugeben folgen

  8. Hab die Seite vorsichtshalber mal gebookmarked. Ist ja alles sehr hilfreich und interessant.
    .-= Massagesessel´s last blog ..Home geändert =-.

  9. Die aktuellste Version meines HMVC-Frameworks erhaltet ihr ab sofort immer hier: http://www.net-developers.de/blog/2011/02/13/download-info-shfw-hmvc-framework-in-php/

Hinterlasse einen Kommentar!

Time limit is exhausted. Please reload the CAPTCHA.

»Informationen zum Artikel

Autor: Simon
Datum: 17.08.2008
Zeit: 15:46 Uhr
Kategorien: Mein MVC-Framework
Gelesen: 36472x heute: 7x

Kommentare: RSS 2.0.
Diesen Artikel kommentieren oder einen Trackback senden.

»Meta