Hackerboard Wiki HaboBlog
Hackerboard bei Facebook Hackerboard bei Google+ Hackerboard bei Twitter

[HaBo]

 
(Web-) Design und webbasierte Sprachen Tipps & Tricks, Designabgleich, HTML & Javascript, Flash, ASP, PHP, Perl/CGI...

Tutorial: Ein FrontController in PHP

Diskussion: Tutorial: Ein FrontController in PHP im Forum (Web-) Design und webbasierte Sprachen, in der Kategorie Web, Network & Multimedia Palace; Anzeige Hallo, da ich jetzt schon des öfteren hier Threads gelesen wie z.B. diesen oder den hier , hab ich ...

Antwort
Alt 05.12.07, 14:57   #1 (permalink)
 
Benutzerbild von BasicAvid
 
Registriert seit: 17.03.04
BasicAvid Leistung: Facit NTK
Likes: 2
Standard Tutorial: Ein FrontController in PHP

Anzeige

Hallo,

da ich jetzt schon des öfteren hier Threads gelesen wie z.B. diesen oder den hier, hab ich mir gedacht ich schreib mal ein Tutorial wie man sowas lösen könnte.

In diesem Tutorial zeig ich euch wie man einen Front Controller, einen AutoLoader und eine ganz kleine Template Klasse in PHP (version 5) schreibt.

Zuerst legen wir die Verzeichnisstruktur und die benötigten Dateien an.

/
| - index.php
| - .htaccess
| + core
| |- FrontController.class.php
| |- AutoLoader.class.php
| |- Template.class.php
| |- Action.class.php
|+ modules
|+ main
|+ actions
| |- Main.class.php
|+ classes
|+templates
| |- Main.tpl.php

Was wofür ist wird später erklärt. Aber schon mal ein kurzes Vorwort zum core und modules Verzeichnis, im core werden nur wichtige Klassen und Libriers abgelegt. Im modules Verzeichnis werden die eigentlichen "Seiten" der Homepage abgelegt. Dazu aber später mehr.

So, jetzt haben wir alle Verzeichnisse und Dateien angelegt die wir brauchen. Beginnen wir also mit der implementierung des Front Controllers.

"Liebe Bastelfreunde, ich hab da schon mal was vorbereitet." ;)

FrontController.class.php

PHP-Code:
<?php
//Hier includieren wir den AutoLoader, den wir aber erst später implementieren
require_once('core/AutoLoader.class.php');

class 
FrontController {
    
    
//Hier wird der Pfad zum Wurzelverzeichnis gespeichert
    
private $rootPath;
    
    
//Singleton Pattern -> Hier wird eine Instanz der FrontControllers gespeichert
    
private static $instance null;
    
    
//Hier wird die Action festgelegt die nach dem Aufruf der Seite angezeigt werden soll. 
    //Das ganze könnte man natürlich auch aus einer Config lesen.
    
private $firstAction 'main.Main';
    
    
//In dieser Variable wird immer die letzte Action gespeichert
    
private $lastAction;
    
    
//Der Konstruktor erwartet als Parameter den Pfad zum Wurzelverzeichnis
    
public function __construct($rootPath) {
        
$this->rootPath $rootPath;
        
//Alle Klasse die man ständig braucht, werden hier geladen.
        
AutoLoader::addPackage('core/Template.class.php');
        
AutoLoader::addPackage('core/Action.class.php');
    }
    
    public function 
__destruct() {
    
    }
    
    
// Der Front Controller wird als Singleton Pattern implementiert, da wir ja nur eine Instanz pro Request haben wollen.
    
public static function getInstance($rootPath null) {
        
// Falls es noch keine Instanz des FrontControllers gibt, wird hier eine instanziert.
        
if (! is_object(self::$instance)) {
            if (
is_null($rootPath)) {
                    throw new 
Exception('Es muss der Rootpfad angegeben werden!');
            }
            
// Instanzieren des Front Controllers 
            
self::$instance = new FrontController($rootPath);
        }
        
// Instanz des FrontControllers zurück geben.
        
return self::$instance;
    }
    
    
// Die run Methode wird bei jedem Request aufgerufen.
    
public function run() {
        
// Hier die aufgerufene Action aus dem Request gelesen.
        
$completeName $_REQUEST['action'];
        
        
// In diesem Codeblock wird geprüft, ob eine Action übergeben/aufgerufen wurde oder nicht.
        // Wenn keine Action übergeben/aufgerufen wurde, wird die First Action ausgeführt.
        
try {
            if (! empty(
$completeName)) {
                
$this->executeAction($completeName);
            } else {
                
$this->executeAction($this->firstAction);
            }
        } catch (
Exception $e) {
            echo 
$e->getMessage();
        }
    }
    
    
//Diese Methode ist das eigentlich Kernstück des Front Controllers.
    // Hier wird geschaut ob es das aufgerufene Module und die Action 
    // überhaupt gibt.
    
private function executeAction($completeName) {
        
// Hier wird der Request String in seine einzelteile zerlegt.
        // Ein Aufruf einer Action sieht folgendermaßen aus,
        // main.Main.html
        //  |         |        |- Wird durch mod-rewrite schon abgeschnitten
        //  |         |- Die Action die ausgeführt werden soll
        //  |- Das Module in der sich die Action befindet
        
$actionName self::getActionName($completeName);
        
$moduleName self::getModuleName($completeName);
        
        
// Hier wird geprüft ob es das Module überhaupt gibt, falls nicht wird eine Exception geworfen
        
if (! is_dir('./modules/' $moduleName)) {
            throw new 
Exception('Das angegebene Modul existiert nicht!');
        }
        
        
// Prüfen, ob es die Action überhaupt gibt, falls nicht wirf dem User eine Exception vor die Füße
        
if (! is_file('./modules/' $moduleName '/actions/' $actionName '.class.php')) {
            throw new 
Exception('Die angegebene Action existiert nicht!');
        }
        
        
// Action includieren
        
require_once('./modules/' $moduleName '/actions/' $actionName '.class.php');
        
        
// Neue Instanz der Action erzeugen
        
$action = new $actionName();
        if (! 
is_object($action)) {
            throw new 
Exception('Die Action konnte nicht initialisiert werden!');
        }
        
        
// Action ausführen
        
try {
            
$action->run();
        } catch (
Exception $e) {
            echo 
$e->getMessage();
        }
        
//lastAction mit der aktuell aufgerufenen Action ersetzen
        
$this->lastAction $completeName;
    }
    
    
// Diese Methode brauchen wir später fürs Template
    
public function includeAction($completeName) {
        
$this->executeAction($completeName);
    }
    
    
//Extrahiert den Actionname aus dem Request String
    
public static function getActionName($completeName) {
        return 
substr($completeNamestrrpos($completeName".") + 1);
    }
    
    
//Extrahiert den Modulename aus dem Request String
    
public static function getModuleName($completeName) {
        return 
substr($completeName0strrpos($completeName"."));
    }
}
?>
Ok, das war schonmal der Front Controller. Jetzt erstellen wir noch schnell die index.php

PHP-Code:
<?php

//Auslesen des Wurzelverzeichnisses
$root dirname(__FILE__);

//FrontController includieren
require_once($root '/core/FrontController.class.php');

// Instanzieren des Front Controllers
$main FrontController::getInstance($root);
if (
is_object($main)) {
    
// Front Controller starten
    
$main->run();
}

?>
Und das ist die index.php, mal überlegen ob ich alles für den ersten Teil habe. Ach ja, stimmt uns fehlt ja noch die .htaccess Datei.

.htaccess
Code:
php_flag register_globals off

# Umschreiben der *.html-URLs in entsprechende action-Parameter:
RewriteEngine on
RewriteRule ^([^/]+)\.html$ index.php?action=$1&mod_rewrite=true [QSA]
Das wars dann auch schon mit dem ersten Teil des Tutorials.
Ich hoffe mal der eine oder andere kann was damit anfangen.

Fragen könnt Ihr ja hier posten oder mir per PM schicken.
__________________
Mfg Basic Avid
- Use it or be used! -
BasicAvid ist offline   Mit Zitat antworten
Alt 05.12.07, 15:53   #2 (permalink)
JTron
Guest
 
Likes:
Standard

Schöne Sache, toll gemacht, obwohl ich eigentlich Ruby bevorzugen würde (Nicht dass ich was gegen PHP hätte, aber Ruby ist einfach bequemer^^). Hoffe auf weitere Tutorials^^.

mfg

JTron
  Mit Zitat antworten
   
HaBOT
 
- Anzeige -

Werbung ist gerade online    
Alt 10.03.08, 17:18   #3 (permalink)
Member of Honour
 
Benutzerbild von easteregg
 
Registriert seit: 14.09.07
easteregg Leistung: Pentium Ieasteregg Leistung: Pentium I
easteregg eine Nachricht über ICQ schicken
Likes: 62
Standard

das klingt sehr interessant.
kannst du mal die .ht files erläutern? ich bin da leider noch nicht sonderlich fit drin!
also was der code macht ist mir klar, aber bitte mal die syntax erläutern...
__________________
» Flattr mich! - Wenn dir mein Beitrag geholfen hat! «
<| 2 AMD Opterons 2384@ 8x3,2ghz | Tyan S2915 | 10GB | 2x 8800GT | 8400GS | Dell 3008WFP + 2x2007FP |>
easteregg ist gerade online   Mit Zitat antworten
Alt 11.03.08, 09:05   #4 (permalink)
Themenstarter
 
Benutzerbild von BasicAvid
 
Registriert seit: 17.03.04
BasicAvid Leistung: Facit NTK
Likes: 2
Standard

Guten Morgen,

hier mal die Erklärung:

"php_flag register_globals off"
Gibt nur an, dass register_globals ausgeschaltet werden soll. Ich geh jetzt nicht näher drauf ein, da ich glaube Du weisst was das bedeutet.

# Umschreiben der *.html-URLs in entsprechende action-Parameter:
RewriteEngine on
Dieses Zeile schaltet die RewriteEngine ein.

RewriteRule ^([^/]+)\.html$ index.php?action=$1&mod_rewrite=true [QSA]

Ok, und hier ist die eigentliche Regel:

^([^/]+)\.html$ --> Ist ein ganz normaler Regulärer Ausdruck.
^ Anfang des Regex
() Definiert eine Gruppe, auf die man mit $n zugreifen kann
[^/] Kein Slash
+ steht für ein beliebiges Zeichen
\.html Am Ende soll ein Punkt und html kommen
$ Ende des Regex

Wie das dann genau ausschaut, zeig ich Dir an einem Beispiel:

main.Main.html wird aufgerufen

Unser Regex trifft zu und formt das ganze zu folgender URL um:

index.php?action=main.Main&mod_rewrite=true

$1 wurde mit der Gruppe in unserem Regex ersetzt. Soweit so gut, nur was passiert wenn wir Parameter übergeben?
Genau, Sie werden ignoriert.

Deshalb steht am Ende folgendes [QSA] = Query String Append. Jetzt werden auch die Parameter mit angehängt.

Der Parameter mod_rewrite=true wird in diesem Tutorial nicht benutzt, man kann Ihn auch weglassen.

So, ich hoffe es ist verständlich erklärt.
__________________
Mfg Basic Avid
- Use it or be used! -
BasicAvid ist offline   Mit Zitat antworten
Alt 11.03.08, 16:57   #5 (permalink)
Member of Honour
 
Benutzerbild von easteregg
 
Registriert seit: 14.09.07
easteregg Leistung: Pentium Ieasteregg Leistung: Pentium I
easteregg eine Nachricht über ICQ schicken
Likes: 62
Standard

ah vielen dank!
aber wenn ich schon das ganze mit htmls mache, wäre es dochschon sinvoller, sämmtliche angaben vor dem .html mit zu verbauen, das wäre für suchmachinen doch sinvoller.

zb sowas dann wie seite-1-hier_kommt_der_themen_name.html

btw, wie ist das, wenn ich das [^/] rausnehmen und damit die slashes zulasse, würde da automatisch die www.domain.com/seite/2/name_des_themas.html auf die /index.php umgeschrieben oder muss ich da ne spezielle configuration mit vornehmen?
__________________
» Flattr mich! - Wenn dir mein Beitrag geholfen hat! «
<| 2 AMD Opterons 2384@ 8x3,2ghz | Tyan S2915 | 10GB | 2x 8800GT | 8400GS | Dell 3008WFP + 2x2007FP |>
easteregg ist gerade online   Mit Zitat antworten
Alt 11.03.08, 23:55   #6 (permalink)
Themenstarter
 
Benutzerbild von BasicAvid
 
Registriert seit: 17.03.04
BasicAvid Leistung: Facit NTK
Likes: 2
Standard

Jein, hier sagen einige dass solche URLs von Google besser geranked werden, andere wiederrum sagen es sei Google egal.

Und hier geht es ja nur darum, die Module+Actions auf vernüftige URLs zu bringen.
Rufst Du z.B. folgende Seite auf, main.Main.html, wird dem FrontController durch die ModRewrite Rule folgendes übergeben, main.Main, der FrontController kann jetzt nachschauen, ob es ein Modul mit dem Namen "main" und der Action "Main" gibt, und diese starten.

Zitat:
btw, wie ist das, wenn ich das [^/] rausnehmen und damit die slashes zulasse, würde da automatisch die www.domain.com/seite/2/name_des_themas.html auf die /index.php umgeschrieben oder muss ich da ne spezielle configuration mit vornehmen?
Ja, das ganze würde dann so aussehen: www.domain.com/seite/2/name_des_themas.html --> http://www.domain.com/index.php?acti...ame_des_themas

Womit aber der Frontcontroller in dieser Version nichts anfangen könnte.
__________________
Mfg Basic Avid
- Use it or be used! -
BasicAvid ist offline   Mit Zitat antworten
Alt 12.03.08, 06:12   #7 (permalink)
Member of Honour
 
Benutzerbild von easteregg
 
Registriert seit: 14.09.07
easteregg Leistung: Pentium Ieasteregg Leistung: Pentium I
easteregg eine Nachricht über ICQ schicken
Likes: 62
Standard

nuja so würde ich dass dann evrwenden, das kannsch mir ja anpassen, das sollte kein problem sein
meine siginfo.de seite soll da nicht so modular werden, da dass ja nur nen privatprojekt ist.
__________________
» Flattr mich! - Wenn dir mein Beitrag geholfen hat! «
<| 2 AMD Opterons 2384@ 8x3,2ghz | Tyan S2915 | 10GB | 2x 8800GT | 8400GS | Dell 3008WFP + 2x2007FP |>
easteregg ist gerade online   Mit Zitat antworten
Alt 12.03.08, 08:28   #8 (permalink)
Themenstarter
 
Benutzerbild von BasicAvid
 
Registriert seit: 17.03.04
BasicAvid Leistung: Facit NTK
Likes: 2
Standard

Falls es Probleme geben sollte bei der Umstellung, kannst Dich ja melden.
__________________
Mfg Basic Avid
- Use it or be used! -
BasicAvid ist offline   Mit Zitat antworten
Alt 12.03.08, 16:58   #9 (permalink)
Member of Honour
 
Benutzerbild von easteregg
 
Registriert seit: 14.09.07
easteregg Leistung: Pentium Ieasteregg Leistung: Pentium I
easteregg eine Nachricht über ICQ schicken
Likes: 62
Standard

ich bin mir noch nicht sicher ob ich deine version hier nutze oder mir das selbst schreibe und ab und zu mir mal ne anregung von dir hole.

was sich dabei im übrigen ergbit, warum die exceptions? was genau haben die für vorteile? hab mit denen noch nie gearbeitet
__________________
» Flattr mich! - Wenn dir mein Beitrag geholfen hat! «
<| 2 AMD Opterons 2384@ 8x3,2ghz | Tyan S2915 | 10GB | 2x 8800GT | 8400GS | Dell 3008WFP + 2x2007FP |>
easteregg ist gerade online   Mit Zitat antworten
Alt 12.03.08, 20:03   #10 (permalink)
Themenstarter
 
Benutzerbild von BasicAvid
 
Registriert seit: 17.03.04
BasicAvid Leistung: Facit NTK
Likes: 2
Standard

Exceptions haben den Vorteil, dass man mit Ihnen eine Saubere Fehlerbehandlung machen kann.

Die meisten benutzen die() oder arbeiten mit errorlevels die Sie mit return oder so zurück geben. Was bei OOP aber nicht gerade sehr schön ist. Exceptions sollten vorallem dort geworfen werden, wo man schon von vornherein weiss hier könnte es krachen.

Mit Exceptions kannst Du z.B. folgendes machen:
PHP-Code:
try {
    
$test = new Test();
    
$test->system('test');
    
$test->openFile('gibts nicht'); // wirft eine FileException -> throw new FileException('Bad file!');    
} catch (SystemException $se) {
    echo 
$se->getMessage();
} catch (
FileException $fe) {
   echo 
$fe->getMessage();
   unset(
$test); // Hier wird das Objekt zerstört
} catch (Exception $e) {


So kannst Du z.B. eine Reihe von Anweisungen in einen try-catch-block setzen, und falls jetzt irgend wo eine Exception geworfen wird, diese fangen und z.B. den Programmfluss weiterlaufen lassen usw.. Man kann sich halt mit Exceptions ein sauberes ErrorHandling aufbauen.
__________________
Mfg Basic Avid
- Use it or be used! -
BasicAvid ist offline   Mit Zitat antworten
Alt 12.03.08, 20:11   #11 (permalink)
 
Registriert seit: 18.03.05
Tasmas Leistung: Facit NTK
Likes: 0
Standard

gabs exception auch schon in PHP4?
Tasmas ist offline   Mit Zitat antworten
Alt 12.03.08, 20:23   #12 (permalink)
Themenstarter
 
Benutzerbild von BasicAvid
 
Registriert seit: 17.03.04
BasicAvid Leistung: Facit NTK
Likes: 2
Standard

Nö, die sind erst mit PHP5 gekommen.
__________________
Mfg Basic Avid
- Use it or be used! -
BasicAvid ist offline   Mit Zitat antworten
Alt 12.03.08, 20:35   #13 (permalink)
Member of Honour
 
Benutzerbild von easteregg
 
Registriert seit: 14.09.07
easteregg Leistung: Pentium Ieasteregg Leistung: Pentium I
easteregg eine Nachricht über ICQ schicken
Likes: 62
Standard

irgendwie... ich bin verwirrt.

PHP-Code:
<?php
 
class test {
   function 
openfile($arg) {
     
fopen($arg,"r");
   }
 }

try {
    
$test = new Test();
    
$test->openFile('gibts nicht');
}
catch (
SystemException $se) {
    
#echo $se->getMessage();
    
echo "hallo";
}
?>
müsste da nich eingentlich nur "hallo" bei rumkommen?

es kommt aber:
Code:
PHP Warning:  fopen(gibts nicht): failed to open stream: No such file or directory in E:\asd.php on line 4
__________________
» Flattr mich! - Wenn dir mein Beitrag geholfen hat! «
<| 2 AMD Opterons 2384@ 8x3,2ghz | Tyan S2915 | 10GB | 2x 8800GT | 8400GS | Dell 3008WFP + 2x2007FP |>
easteregg ist gerade online   Mit Zitat antworten
Alt 12.03.08, 20:51   #14 (permalink)
 
Registriert seit: 18.03.05
Tasmas Leistung: Facit NTK
Likes: 0
Standard

Zitat:
Original von BasicAvid
Nö, die sind erst mit PHP5 gekommen.
ah dacht ichs doch! Danke für die Info!
Tasmas ist offline   Mit Zitat antworten
Alt 12.03.08, 20:54   #15 (permalink)
Member of Honour
 
Benutzerbild von easteregg
 
Registriert seit: 14.09.07
easteregg Leistung: Pentium Ieasteregg Leistung: Pentium I
easteregg eine Nachricht über ICQ schicken
Likes: 62
Standard

ah, bin selbst drauf gekommen ... my fault!


was ist eigentlich der vorteil der instanzierung anstatt der initialisierung via $controller = new Frontcontroller(); ?
__________________
» Flattr mich! - Wenn dir mein Beitrag geholfen hat! «
<| 2 AMD Opterons 2384@ 8x3,2ghz | Tyan S2915 | 10GB | 2x 8800GT | 8400GS | Dell 3008WFP + 2x2007FP |>
easteregg ist gerade online   Mit Zitat antworten
Antwort
   
- Anzeige -

Werbung ist gerade online    

[HaBo] » Web, Network & Multimedia Palace » (Web-) Design und webbasierte Sprachen » Tutorial: Ein FrontController in PHP
Themen-Optionen
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind aus
Pingbacks sind aus
Refbacks sind aus


Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
PHP - Tutorial: Ein FrontController in PHP Mackz Programmierung 0 18.03.08 23:10
php pdf Tutorial ? 007Rene (Web-) Design und webbasierte Sprachen 5 11.06.07 15:56
Tutorial silenced Fun Section 4 30.08.05 23:33
c++ tutorial Sebastian_1 Downloads 4 19.04.05 17:49


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61