php.de

Zurück   php.de > Webentwicklung > Software-Design

Software-Design Diskussionen auf Profi-Niveau: PHP Lösungen auf konzeptioneller Ebene

Antwort
 
LinkBack Themen-Optionen Bewertung: Bewertung: 1 Stimmen, 5,00 durchschnittlich.
Alt 06.02.2011, 03:10  
Erfahrener Benutzer
 
Registriert seit: 06.11.2008
Beiträge: 212
stayInside befindet sich auf einem aufstrebenden Ast
Standard Meine Autoload Klasse

Hallo,

zur Zeit entwickel ich mein eigenes Framework. Dies dient überwiegend zum lernen, soll später aber auch als Grundlage für Projekte dienen.

Da ich soeben meine Autoload-Klasse fertiggestellt habe (bisschen Doku und Fehler abfangen fehlt noch) möchte ich diese gerne mal öffentlich zur Diskussion stellen.

Hier die Aufgaben die die Klasse erfüllen sollte:

- Soll die Dateien automatisch in bestimmten Ordnern suchen und einbinden

- Damit bei großen Ordner nicht jedesmal der Ordner durchsucht werden muss soll eine Cache Datei erstellt werden mit allen Klassenpfaden

- Der Cache soll sich automatisch aktualisieren wenn eine neu erstellte Klasse aufgerufen wird

PHP-Code:
<?php

/*
 * Verhindert das die Datei direkt aufgerufen werden kann
 */
if (defined('SCRIPT') === false) die('The file can not be called directly!');

final class 
Autoload
{
    
/**
     * Beschreibung
     *
     * @static
     *
     * @var Autoload
     */
    
private static $objInstance;

    
/**
     * Beschreibung
     *
     * @var string
     */
    
private $strExtension;

    
/**
     * Beschreibung
     *
     * @var string
     */
    
private $strCachePath;

    
/**
     * Beschreibung
     *
     * @var array
     */
    
private $arrRegister = array();

    
/**
     * Beschreibung
     *
     * @var array
     */
    
private $arrClassRegister = array();

    
/**
     * Autoload::__clone()
     *
     * Beschreibung
     *
     * @author xxx
     *
     * @access private
     *
     * @final
     *
     * @return void
     */
    
private final function __clone() {}

    
/**
     * Autoload::__construct()
     *
     * Beschreibung
     *
     * @author xxx
     *
     * @access private
     *
     * @final
     *
     * @return void
     */
    
private final function __construct() {}

    
/**
     * Autoload::getInstance()
     *
     * Beschreibung
     *
     * @author xxx
     *
     * @access public
     *
     * @static
     * @final
     *
     * @return Autoload
     */
    
public static final function getInstance()
    {
        if (
is_object(self :: $objInstance) === false)
        {
            
self :: $objInstance = new Autoload();
        }

        return (
self :: $objInstance);
    }

    
/**
     * Autpload::activate()
     *
     * Beschreibung
     *
     * @author xxx
     *
     * @access public
     *
     * @static
     * @final
     *
     * @return void
     */
    
public function activate()
    {
        
spl_autoload_register(array
        (
            
$this,
            
'load'
        
));
    }

    
/**
     * Autpload::setExtension()
     *
     * Beschreibung
     *
     * @author xxx
     *
     * @access public
     *
     * @final
     *
     * @param string $strExtension
     *
     * @return void
     */
    
public final function setExtension($strExtension)
    {
        
$this->strExtension $strExtension;

        
spl_autoload_extensions($strExtension);
    }

    
/**
     * Autoload::setCacheFolder()
     *
     * Beschreibung
     *
     * @author xxx
     *
     * @access public
     *
     * @final
     *
     * @param string $strFolderPath
     *
     * @return boolean Bestätigung ob der Ordner gefunden werden konnte
     */
    
public final function setCacheFolder($strFolderPath$blnCreateFolder true)
    {
        
/*
         * Der Ordner ist nicht vorhanden und wird, wenn gewünscht, erstellt
         */
        
if (is_dir($strFolderPath) === false &&
            
$blnCreateFolder === true)
        {
            
mkdir($strFolderPath0755true);
        }

        
/*
         * Es konnte kein Ordner erstellt oder gefunden werden
         */
        
if (is_dir($strFolderPath) === false)
        {
            return (
false);
        }

        
$this->strCachePath $strFolderPath;

        return (
true);
    }

    
/**
     * Autoload::register()
     *
     * Beschreibung
     *
     * @author xxx
     *
     * @access public
     *
     * @final
     *
     * @param string     $strPath
     * @param string     $strCacheName
     * @param boolean     $blnForceLoad
     *
     * @return void
     */
    
public final function register($strPath$strCacheName null$blnForceLoad false)
    {
        
/*
         * Der übergebene Ordner existiert nicht
         */
        
if (is_dir($strPath) === false)
        {
            
/*
             * TODO: hier passiert noch was?
             */
        
}

        
/*
         * Es wurde kein Cache-Name gewählt
         */
        
if (empty($strCacheName) === true)
        {
            
$strCacheName sha1($strCacheName);
        }

        
/*
         * Der Cache-Name enthält ungültige Zeichen
         */
        
if ((boolean) preg_match('#[^a-zA-Z0-9]#si'$strCacheName) === true)
        {
            
/*
             * TODO: hier passiert noch was?
             */
        
}

        
/*
         * Der Pfad wird in der Registry gespeichert
         */
        
$this->arrRegister[$strCacheName] = $strPath;

        
/*
         * Es gibt bereits eine Cache-Datei zu diesem Name (Cache-Verzeichnis muss gesetzt sein) sofern das neu schreiben des Caches nicht erzwungen wird
         */
        
if (empty($this->strCachePath) === false &&
            
file_exists($this->strCachePath $strCacheName '.cache.php') &&
            
$blnForceLoad === false)
        {
            return;
        }

        
/*
         * Alle Dateien mit der entsprechenden Dateiendung im Ordner ermitteln
         */
        
$objDirectory        = new RecursiveDirectoryIterator($strPath);
        
$objIterator        = new RecursiveIteratorIterator($objDirectory);
        
$objRegexIterator    = new RegexIterator($objIterator'#^.+' preg_quote($this->strExtension'#') . '$#si'RecursiveRegexIterator :: GET_MATCH);

        
/*
         * Wenn der Cache aktiviert ist oder der Cache aktiviert und erzwungen wird
         */
        
if (empty($this->strCachePath) === false ||
            (empty(
$this->strCachePath) === false && $blnForceLoad === true))
        {
            
$this->writeCache($strCacheName$objRegexIterator);
        }
        else
        {
            
$this->writeClassRegisterFromIterator($objRegexIterator);
        }
    }

    
/**
     * Autoload::loadCache()
     *
     * Beschreibung
     *
     * @author xxx
     *
     * @access private
     *
     * @final
     *
     * @return void
     */
    
private final function loadCache()
    {
        
/*
         * Cache-Dateien ermitteln
         */
        
$objDirectory        = new RecursiveDirectoryIterator($this->strCachePath);
        
$objIterator        = new RecursiveIteratorIterator($objDirectory);
        
$objRegexIterator   = new RegexIterator($objIterator'#^.*' preg_quote('.cache.php''#') . '$#si'RecursiveRegexIterator :: GET_MATCH);

        foreach (
$objRegexIterator as $arrCacheFilePath)
        {
            if (
file_exists($arrCacheFilePath[0]) === true)
            {
                include (
$arrCacheFilePath[0]);

                
$arrCache = (array) unserialize($arrCache);

                
$this->writeClassRegisterFromCache($arrCache);
            }
        }
    }

    
/**
     * Autoload::writeCache()
     *
     * Beschreibung
     *
     * @author xxx
     *
     * @access private
     *
     * @final
     *
     * @param string $strCacheName
     * @param RegexIterator $objRegexIterator
     *
     * @return void
     */
    
private final function writeCache($strCacheNameRegexIterator $objRegexIterator)
    {
        
$strCacheFile $this->strCachePath $strCacheName '.cache.php';

        
$resHandle fopen($strCacheFile'w+');

        
/*
         * Es konnte kein Stream zur Datei aufgebaut werden
         */
        
if (is_resource($resHandle) === false)
        {
            
/*
             * TODO: hier passiert noch was?
             */
        
}

        
/*
         * Die Datei kann nicht geschrieben werden
         */
        
if (is_writeable($strCacheFile) === false)
        {
            
/*
             * TODO: hier passiert noch was?
             */
        
}

        
$arrCache = array();

        foreach (
$objRegexIterator as $arrPath)
        {
            
$strBasename basename($arrPath[0]);
            
$strBasename mb_substr($strBasename0mb_stripos($strBasename'.'));

            
$arrCache[$strBasename] = $arrPath[0];
        }

        
fputs($resHandle'<?php $arrCache = \'' .serialize($arrCache) . '\'; ?>');

        
fclose($resHandle);
    }

    
/**
     * Autoload::writeClassRegisterFromIterator()
     *
     * Beschreibung
     *
     * @author xxx
     *
     * @access private
     *
     * @final
     *
     * @param RegexIterator $objRegexIterator
     *
     * @return void
     */
    
private final function writeClassRegisterFromIterator(RegexIterator $objRegexIterator)
    {
        foreach (
$objRegexIterator as $arrPath)
        {
            
/*
             * Der Klassenname wird aus dem Pfad ermittelt
             */
            
$strBasename basename($arrPath[0]);
            
$strBasename mb_substr($strBasename0mb_stripos($strBasename'.'));

            
$this->arrClassRegister[$strBasename] = $arrPath[0];
        }
    }

    
/**
     * Autoload::writeClassRegisterFromCache()
     *
     * Beschreibung
     *
     * @author xxx
     *
     * @access private
     *
     * @final
     *
     * @param array $arrCache
     *
     * @return void
     */
    
private final function writeClassRegisterFromCache(array $arrCache)
    {
        foreach (
$arrCache as $strClassName => $strClassPath)
        {
            
$this->arrClassRegister[$strClassName] = $strClassPath;
        }
    }

    
/**
     * Autoload::load()
     *
     * Beschreibung
     *
     * @author xxx
     *
     * @access private
     *
     * @final
     *
     * @param string     $strClass
     * @param boolean     $blnRecursive
     *
     * @return boolean
     */
    
private final function load($strClass$blnRecursive false)
    {
        
/*
         * Wenn ein Cache-Verzeichnis gesetzt ist wird versucht der Cache zu laden
         */
        
if (empty($this->strCachePath) === false &&
            empty(
$this->arrClassRegister) === true)
        {
            
$this->loadCache();
        }

        
/*
         * Die Datei mit dem Klassennamen existiert
         */
        
if (empty($this->arrClassRegister[$strClass]) === false &&
            
file_exists($this->arrClassRegister[$strClass]) === true)
        {
            require_once (
$this->arrClassRegister[$strClass]);
        }

        
/*
         * Es wird einmal versucht die Klasse zu ermitteln indem der Cache aktualisiert wird
         */
        
else if ($blnRecursive === false)
        {
            foreach (
$this->arrRegister as $strCache => $strCachePath)
            {
                
$this->register($strCachePath$strCachetrue);
            }

            return (
$this->load($strClasstrue));
        }

        
/*
         * Die Klasse existiert in dieser Datei nicht
         */
        
if (class_exists($strClassfalse) === false)
        {
            
trigger_error('Möp');

            return (
false);
        }

        return (
true);
    }
}

?>
Hier mal ein Beispiel wie man die Klasse benutzt:

PHP-Code:
$objAutoload Autoload :: getInstance();

/*
 * Dateiendung für den Autoloader festlegen
 */
$objAutoload->setExtension('.class.php');

/*
 * Cacheverzeichnis für den Autloader festlegen
 */
$objAutoload->setCacheFolder(Registry :: get('CacheAutoloadPath'));

/*
 * Verzeichnisse und Cachenamen für den Autoloader festlegen
 */
$objAutoload->register(Registry :: get('CoreLibraryPath'),                'CoreLibrary');
$objAutoload->register(Registry :: get('CoreInterfacePath'),            'CoreInterface');
$objAutoload->register(Registry :: get('ApplicationControllerPath'),    'ApplicationController');

/*
 * Autoloader aktivieren
 */
$objAutoload->activate(); 
So, dann sagt mal eure Meinung, egal ob positiv oder negativ.
stayInside ist offline   Mit Zitat antworten
Sponsor Mitteilung
PHP Code Flüsterer

Registriert seit: 21.08.2005
Beiträge: 4682
PHP-Kenntnisse:
Fortgeschritten

Alt 06.02.2011, 10:39  
Moderator und Wett-König
 
Benutzerbild von dr.e.
 
Registriert seit: 21.05.2008
Beiträge: 3.657
PHP-Kenntnisse:
Fortgeschritten
dr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblick
dr.e. eine Nachricht über Skype™ schicken
Standard

Hallo,

ich würde kein trigger_error() verwenden, sondern eine Exception werfen. Ansonsten möchte ich den Code nicht beurteilen, da ich das Autoloading-Konzept für absoluten Schwachsinn halte. Es verstümmelt Klassen-Namen zwingt flache Strukturen auf und verhindert damit jedwede Freiheit hinsichtlich vernünftiger Strukturiering von Quellcode.
__________________
Viele Grüße,
Dr.E.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1. Think about software design before you start to write code!
2. Discuss and review it together with experts!
3. Choose good tools (-> Adventure PHP Framework (APF))!
4. Write clean and reusable software only!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dr.e. ist offline   Mit Zitat antworten
Alt 06.02.2011, 10:47  
Benutzer
 
Benutzerbild von ALEC23
 
Registriert seit: 25.08.2009
Beiträge: 80
PHP-Kenntnisse:
Anfänger
ALEC23 befindet sich auf einem aufstrebenden Ast
Standard

Moin Dr. E.,

ich versuche seit einiger Zeit meine Anwendungen komplett objektorientiert umzusetzen und lade meine Klassen auch via Autoloader (SPL) in die Anwendung. Könntest Du mir bitte nachfolgendes Statement ein wenig erläutern?

Zitat:
Zitat von dr.e. Beitrag anzeigen
...Es verstümmelt Klassen-Namen zwingt flache Strukturen auf und verhindert damit jedwede Freiheit hinsichtlich vernünftiger Strukturiering von Quellcode...
Ich bedanke mich.
ALEC23 ist offline   Mit Zitat antworten
Alt 06.02.2011, 10:58  
Erfahrener Benutzer
 
Benutzerbild von litterauspirna
 
Registriert seit: 24.04.2008
Beiträge: 3.172
PHP-Kenntnisse:
Anfänger
litterauspirna sorgt für eine eindrucksvolle Atmosphärelitterauspirna sorgt für eine eindrucksvolle Atmosphäre
litterauspirna eine Nachricht über ICQ schicken
Standard

Zitat:
Zitat von dr.e. Beitrag anzeigen
Hallo,

ich würde kein trigger_error() verwenden, sondern eine Exception werfen. Ansonsten möchte ich den Code nicht beurteilen, da ich das Autoloading-Konzept für absoluten Schwachsinn halte. Es verstümmelt Klassen-Namen zwingt flache Strukturen auf und verhindert damit jedwede Freiheit hinsichtlich vernünftiger Strukturiering von Quellcode.
Hallo Doc,

könntest du das vieleicht etwas nähe begründen? Würde mich mal interessieren warum du so denkst und was du für die bessere Alternative hältst.

Danke dir. Gruß Litter
__________________
Aus dem Dynamo Lande kommen wir. Trinken immer reichlich kühles Bier. Und dann sind wir alle voll, die Stimmung ist so toll. Aus dem Dynamo Lande kommen wir.
http://www.lit-web.de
litterauspirna ist offline   Mit Zitat antworten
Alt 06.02.2011, 12:12  
fab
Erfahrener Benutzer
 
Benutzerbild von fab
 
Registriert seit: 28.07.2010
Beiträge: 2.308
PHP-Kenntnisse:
Fortgeschritten
fab ist ein Lichtblickfab ist ein Lichtblickfab ist ein Lichtblickfab ist ein Lichtblickfab ist ein Lichtblick
Standard

Ein paar Kleinigkeiten, die mir aufgefallen sind:

1. final function in final class - nicht schlimm aber irgendwie doppelt gemoppelt

2. warum der explizite Aufruf von activate()? Ich würde dies im Konstruktor machen, denn du wirst den Autoloader wohl kaum instantiieren wenn du nicht beabsichtigst, ihn zu verwenden.

3.
PHP-Code:
        /*
         * Es wurde kein Cache-Name gewählt
         */
        
if (empty($strCacheName) === true)
        {
            
$strCacheName sha1($strCacheName);
        } 
Ergibt so keinen Sinn, ich nehme an, du meinst sha1($strPath)? Außerdem: empty() gibt immer boolean zurück, === true kannst du dir also sparen.

4. Allgemein ist die Verwendung von === begrüßenswert aber mit deinem === true in den if-Statements übertreibst du es IMHO. Besonders schön sieht man das hier:
PHP-Code:
if ((boolean) preg_match('#[^a-zA-Z0-9]#si'$strCacheName) === true
preg_match gibt immer entweder 1 oder 0 zurück, was wunderbar ohne weiteres als boolean true oder false interpretiert wird, du castest aber erst noch um unbedingt einen echten boolean zu haben und hängst dann noch ein völlig renundantes === true dran. Selbst in Java wäre das übertrieben

5. vielleicht Geschmackssache aber bei solchen Cache-Files finde ich es schöner, return zu benutzen anstatt Variablen zu belegen, so ist auch im Code direkt ersichtlich woher der Wert kommt ($arrCache muss man bei dir erstmal suchen).
PHP-Code:
// generated cache file
<?php return array(...); ?>

// loadCache method
<?php
...
$arrCache = include($arrCacheFilePath[0]); 
...
?>
Wie gesagt, Kleinigkeiten. Ansonsten erscheint mir das Konzept mit dem Caching auf den ersten Blick recht schlüssig, was mir fehlen würde ist Namespace-Unterstützung oder übersehe ich etwas?
fab ist offline   Mit Zitat antworten
Alt 06.02.2011, 12:22  
moderatives Dielektrikum
 
Benutzerbild von nikosch
 
Registriert seit: 21.05.2008
Beiträge: 35.994
PHP-Kenntnisse:
Fortgeschritten
nikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunft
Standard

Ich würde sogar noch weiter gehen. Durch die eine Variable die dort übergeben wird:
Zitat:
PHP-Code:
                include ($arrCacheFilePath[0]);

                
$arrCache = (array) unserialize($arrCache); 
gibt es eigentlich keinen Vorteil gegenüber dieser Lösung:
PHP-Code:
                $arrCache unserialize(file_get_contents ($arrCacheFilePath[0])); 
Vorteil: Ein unvollständiges Cachefile schießt mir nicht die Anwendung ab.
Einen serialisierten String als Variable abzulegen und das zu includen ist irgendwie doppelt gemoppelt.

Ansonsten stören mich an der Klasse die massiven Filesystemzugriffe. Wieso kann man nicht alles in einem Cachefile ablegen oder die Handvoll Registrierungen einfach als Array zuweisen?
__________________
--
One pixel is still too big. Please make it smaller. ASAP.

Initiative Mittelstand.
Die wichtigste Gestaltungsregel im Screendesign ist Pi mal Daumen des Arbeitgebers.
--
nikosch ist gerade online   Mit Zitat antworten
Alt 06.02.2011, 14:13  
Moderator und Wett-König
 
Benutzerbild von dr.e.
 
Registriert seit: 21.05.2008
Beiträge: 3.657
PHP-Kenntnisse:
Fortgeschritten
dr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblick
dr.e. eine Nachricht über Skype™ schicken
Standard

Hallo Alec32, hallo litter,

der Autoload-Mechanismus von PHP ist die Idee, Klassen-Namen zu nutzen um die zugehörige Implementierung zu laden. Sofern der Anspruch besteht, den Code einer Anwendung hinsichtlich seiner Nutzung, seiner Bedeutung und seiner Abhängigkeit zu strukturieren, ist man gezwungen, diese Strukturen in den Klassen-Namen abzubilden. Seinen Höhepunkt erreicht das im Autoloading des ZF, in dem die Namespaces in den Klassen abgebildet sind (z.B. Zend_Foo_Bar, das auf Zend/Foo/Bar.php mappt). Damit sind Klassen-Namen nicht nur unaussprechlich, sondern IMHO auch falsch hinsichtlich des OO-Gadankens, die Realität abbilden zu wollen.
Möchte ich mit Autoloading nun eine Klasse Frontcontroller aus dem Namespace core::frontcontroller laden müsste ich diese entweder Core_Frontcontroller_Frontcontroller nennen oder auf explizite Abhängigkeits-Definition (=require/include/...) ausweichen. Letzteres halte ich bei den aktuellen Mitteln, die mir PHP 5.2.X bietet für die deutlich bessere Variante.

Sollte sich PHP 5.3.X in vielleicht einem Jahr durchgesetzt haben, so könnte man drüber nachdenken, Autoloading vielleicht doch zu nutzen, denn ein

PHP-Code:
use corefrontcontrollerFrontcontroller 
würde dann den kompletten Namespace und die Klasse selbst beinhalten. Dies lässt sich dann zum jeweils relevanten Datei-Namen der Klassen-Implementierung auflösen und die Klasse einbinden. Dies ist jedoch auch in PHP 5.3.X nicht möglich, wenn ich einfach nur ein

PHP-Code:
$fC = new Frontcontroller(); 
im Code notiere. Davon abgesehen, ist es - hierbei bin ich ein Fan von JAVA und C# - für die bewusste Implementierung ohnehin schlauer, Abhängigkeiten explizit zu definieren. Das macht nicht nur klar, was ich hier nutzen möchte, sondern erleichtert es auch statischen Code-Analyse-Werkzeugen Abhängigkeiten (vielleicht auch zirkulärer Art) zu erkennen und zu bewerten.

Aus eben den genannten Gründen setzt das APF auf statische Abhängigkeiten und verzichtet auf Autoloading. Sofern du eine vernünftige IDE einsetzt ist das auch weiter kein Problem, da ohnehin alle Klassen für intelli sense indiziert sind und du damit dahingehend keine Nachteile beim Entwickeln hast.

Meiner Ansicht nach taugt Autoload/SPL Autoload solange nichts, bis nicht eine Integration von Namespaces stattgefunden hat und eine Klasse nicht mehr nur durch ihren Namen sondern vor allem durch ihren Namespace und Namen adressiert werden muss. In PHP 5.3.X ist das Adressieren ja schon möglich aber nicht zwingend notwendig. Nutzt man use, oder explizite Instanziierungen kann Autoloading nützlich sein, rund ist das Feature aber IMHO noch lange nicht.

Bis dahin bleibe ich ein Fan von expliziten Abhängigkeiten.
__________________
Viele Grüße,
Dr.E.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1. Think about software design before you start to write code!
2. Discuss and review it together with experts!
3. Choose good tools (-> Adventure PHP Framework (APF))!
4. Write clean and reusable software only!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dr.e. ist offline   Mit Zitat antworten
Alt 06.02.2011, 14:44  
Erfahrener Benutzer
 
Benutzerbild von litterauspirna
 
Registriert seit: 24.04.2008
Beiträge: 3.172
PHP-Kenntnisse:
Anfänger
litterauspirna sorgt für eine eindrucksvolle Atmosphärelitterauspirna sorgt für eine eindrucksvolle Atmosphäre
litterauspirna eine Nachricht über ICQ schicken
Standard

Zitat:
Zitat von dr.e. Beitrag anzeigen
Bis dahin bleibe ich ein Fan von expliziten Abhängigkeiten.
Das heißt du notierst im Code wo du es brauchst z.B.

PHP-Code:
include 'FrontController.php'
Habe ich das richtig verstanden?

Ich frage deshalb, weil ich grad anfange meine ersten Schritte mit MVC zu machen. Ich habe einen FrontController und lade da momentan durch Adressierung aus der URL meine Models, Subcontroller und Views die ich brauche. Das heist anhand eines in der URL stehenden Parameters. Diesen Parameter oder auch 2, jenachdem, habe ich dann in der Dateibenamung und im Klassennamen stehen. Momentan funktioniert das auch gut, aber wenn ich eben so deine Zeilen lese bekomme ich grad doch ein wenig Zweifel ob das so der richtige Weg ist.
__________________
Aus dem Dynamo Lande kommen wir. Trinken immer reichlich kühles Bier. Und dann sind wir alle voll, die Stimmung ist so toll. Aus dem Dynamo Lande kommen wir.
http://www.lit-web.de
litterauspirna ist offline   Mit Zitat antworten
Alt 06.02.2011, 15:23  
Erfahrener Benutzer
 
Registriert seit: 06.11.2008
Beiträge: 212
stayInside befindet sich auf einem aufstrebenden Ast
Standard

Zitat:
Zitat von fab Beitrag anzeigen
Ein paar Kleinigkeiten, die mir aufgefallen sind:

1. final function in final class - nicht schlimm aber irgendwie doppelt gemoppelt

2. warum der explizite Aufruf von activate()? Ich würde dies im Konstruktor machen, denn du wirst den Autoloader wohl kaum instantiieren wenn du nicht beabsichtigst, ihn zu verwenden.

3.
PHP-Code:
        /*
         * Es wurde kein Cache-Name gewählt
         */
        
if (empty($strCacheName) === true)
        {
            
$strCacheName sha1($strCacheName);
        } 
Ergibt so keinen Sinn, ich nehme an, du meinst sha1($strPath)? Außerdem: empty() gibt immer boolean zurück, === true kannst du dir also sparen.

4. Allgemein ist die Verwendung von === begrüßenswert aber mit deinem === true in den if-Statements übertreibst du es IMHO. Besonders schön sieht man das hier:
PHP-Code:
if ((boolean) preg_match('#[^a-zA-Z0-9]#si'$strCacheName) === true
preg_match gibt immer entweder 1 oder 0 zurück, was wunderbar ohne weiteres als boolean true oder false interpretiert wird, du castest aber erst noch um unbedingt einen echten boolean zu haben und hängst dann noch ein völlig renundantes === true dran. Selbst in Java wäre das übertrieben

5. vielleicht Geschmackssache aber bei solchen Cache-Files finde ich es schöner, return zu benutzen anstatt Variablen zu belegen, so ist auch im Code direkt ersichtlich woher der Wert kommt ($arrCache muss man bei dir erstmal suchen).
PHP-Code:
// generated cache file
<?php return array(...); ?>

// loadCache method
<?php
...
$arrCache = include($arrCacheFilePath[0]); 
...
?>
Wie gesagt, Kleinigkeiten. Ansonsten erscheint mir das Konzept mit dem Caching auf den ersten Blick recht schlüssig, was mir fehlen würde ist Namespace-Unterstützung oder übersehe ich etwas?
1. Klingt logisch. Habe ich bislang noch nicht drüber nachgedacht gehabt.

2. Ich hatte es erst im Konstruktor, habe dann allerdings die activate() eingepflegt weil ich vor dem aktivieren noch ein paar Sachen prüfen wollte (Einstellungen alle gültig etc.). Aber da dies direkt in den jeweiligen Methoden schon gemacht wird wird die activate() wieder in den Konstruktor verfrachtet.

3. Stimmt, sollte $strPath sein. Code den man Nachts um 3 produziert sollte man wirklich am nächsten Tag nochmal kontrollieren

4. Angewohnheit von mir. Ich prüfe stets mit === um Typenfehler zu vermeiden, bei dem preg_match() sehe ich es aber ein das es Schwachsinn ist.

5. Ich war lange am überlegen wie ich verdeutlichen kann woher $arrCache kommt, kam aber bislang nie auf eine Lösung, danke für den Denkanstoß. Wobei ich da das Vorgehen von nikosch eher bevorzuge. Das spart auch nochmal ein paar Bytes (PHP Tag etc.) und bindet mich nicht an eine .php Endung.


Ansonsten muss ich sagen das dr.e mich zum nachdenken gebracht hat, besonders der folgende Satz

Zitat:
Davon abgesehen, ist es - hierbei bin ich ein Fan von JAVA und C# - für die bewusste Implementierung ohnehin schlauer, Abhängigkeiten explizit zu definieren. Das macht nicht nur klar, was ich hier nutzen möchte, sondern erleichtert es auch statischen Code-Analyse-Werkzeugen Abhängigkeiten (vielleicht auch zirkulärer Art) zu erkennen und zu bewerten.
Mal schauen was sich aus dieser Diskussion noch so wird.
stayInside ist offline   Mit Zitat antworten
Alt 06.02.2011, 16:55  
Moderator und Wett-König
 
Benutzerbild von dr.e.
 
Registriert seit: 21.05.2008
Beiträge: 3.657
PHP-Kenntnisse:
Fortgeschritten
dr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblick
dr.e. eine Nachricht über Skype™ schicken
Standard

@litter:

Zitat:
Habe ich das richtig verstanden?
Korrekt.

Zitat:
Ich frage deshalb, weil ich grad anfange meine ersten Schritte mit MVC zu machen. Ich habe einen FrontController und lade da momentan durch Adressierung aus der URL meine Models, Subcontroller und Views die ich brauche.
Das ist prinzipiell eine valide Vorgehensweise. MVC wird oft zusammen mit dem Frontcontroller-Pattern implementiert, da gewisse Probleme nicht direkt mit MVC zu tun haben, jedoch auch generisch abgebildet werden sollten. Implementierst du ein hierarchisches MVC-Modell sind wieder andere Mechanismen notwendig. Was oft missinterpretiert wird ist, dass der Frontcontroller (mehr oder weniger) zu MVC gehört. Um das bei deiner Implementierung aber genauer beurteilen zu können, müsste ich mir den Code mal ansehen. "Subcontroller" klingt mir aber nach einem hierarchischen Modell bzw. einer Vermischung von MVC und Frontcontroller, was nicht in jedem Fall korrekt ist. MVC ist nur dann korrekt interpretiert, wenn du zwischen Front-Controller-Command bzw. -Action unterscheidest. Die Front-Controller-Action kannst du dann als Router oder Input-Filter nutzten der den MVC-Controller ausführt. Der Frontcontroller - das hatte ich in einer Diskussion neulich schon mal angesprochen - darf nichts von MVC selbst wissen, sonst ist er nicht generisch einsetztbar.

Aus den genannten Gründen trennt das APF beispielsweise zwischen Front-Controller, der das gleichnamige Pattern generisch implementiert und einem Page-Controller, der sich um das (H)MVC kümmert. So kannst du den Front-Controller in vielen Applikationen ohne Software-Änderung einsetzen. Gleiches gilt für den Page-Controller, der noch dazu den Vorteil bietet, HMVC zu ermöglichen. Damit bist du noch ein Stück weiter unabhängig in deinem URL-Layout (siehe unten).

Zitat:
Das heist anhand eines in der URL stehenden Parameters. Diesen Parameter oder auch 2, jenachdem, habe ich dann in der Dateibenamung und im Klassennamen stehen. Momentan funktioniert das auch gut, aber wenn ich eben so deine Zeilen lese bekomme ich grad doch ein wenig Zweifel ob das so der richtige Weg ist.
Ich würde die URL nie 1:1 auf Klassen abbilden. Einige Implementierungen von MVC handhaben das so, dass ein /index eine IndexAction aufruft oder ein /foo/bar die Methode FooAction::bar(). Das ist in meinen Augen aber ein Fehler, denn du machst dein URL-Layout abhängig von deiner technischen Umsetzung. Möchtest du die URL nun aus SEO- oder aus Konsistenz-Gründen anpassen, ändern oder redesignen, dann hast änderst du zig Stellen im Code. Das muss meiner Ansicht nach transparent gehalten werden.

Aus diesem Grund besitzt das APF beispielsweise Input- und Output-Filter, die das URL-Layout von einer externen Repräsentation in eine interne übersetzten können. So ist es ohne eine Zeile Software-Änderung möglich von einem auf das andere Layout zu switchen.

Darf ich fragen, wie du dir MVC gerade zu gemüte führst? Nutzt du ein Framework oder eine eigene Implementierung?
__________________
Viele Grüße,
Dr.E.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1. Think about software design before you start to write code!
2. Discuss and review it together with experts!
3. Choose good tools (-> Adventure PHP Framework (APF))!
4. Write clean and reusable software only!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dr.e. ist offline   Mit Zitat antworten
Antwort


Themen-Optionen
Thema bewerten
Thema bewerten:

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

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

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
Seite nur im Script aufrufbar BlackScorp PHP Tipps 2010 4 03.11.2010 15:57
[Erledigt] Klasse aus einer anderen Klasse aufrufen Tobby PHP-Fortgeschrittene 7 14.07.2010 20:05
Autoload: Klasse wird nicht eingebunden, obwohl der Pfad stimmt nuna PHP Tipps 2010 7 04.06.2010 14:03
[Erledigt] Nur einer bestimmten Klasse Zugriff andere Klasse erlauben Turamisi Software-Design 2 20.02.2010 20:31
Klasse für Objekteigenschaft erzeugen? Asipak PHP-Fortgeschrittene 25 30.05.2009 19:45
[Erledigt] Eine klasse einbinden newWorldOrder PHP Tipps 2009 2 23.02.2009 19:32
Mini-Tutorial: Autoload Exception bei nichtgefundener klasse brian johnson Wiki Diskussionsforum 10 23.01.2009 22:18
Methode einer anderen Klasse aufrufen Luka PHP-Fortgeschrittene 15 09.11.2008 14:19
Klasse aus externer Klasse aufrufen kostja PHP Tipps 2008 8 07.08.2008 14:13
Variable aus Klasse herausbekommen GSJLink PHP Tipps 2008 7 16.02.2008 22:25
String-Parser Klasse - was muss rein? Matze PHP Tipps 2007 2 08.04.2007 22:14
mehr als eine Klasse einbinden Alpha Centauri PHP-Fortgeschrittene 4 13.04.2006 20:56
Instanz einer Klasse in einer anderen Klasse verwenden Buhmann PHP-Fortgeschrittene 7 28.10.2005 23:12
[Erledigt] Führerschein für Klasse A+B.. Preis OK??? Off-Topic Diskussionen 20 13.07.2005 18:44
Klasse ändern UniQ PHP Tipps 2004 5 24.08.2004 14:46

Besucher kamen über folgende Suchanfragen bei Google auf diese Seite
java autoload class, php autoloader klasse, php autoload einbinden, php autoload, autoload klasse, eigene autoload klasse, php namespaces autoload tutorial, php klasse aus klasse einbinden autoload, php autoload klasse, create a mvc frontcontroller php 5.3, spl_autoload_register class hierarchie, __autoload php in klasse, php class autoloader, php autoload pfad anhand klassennamen ermitteln, meine autoload php tutorial, script automatische laden von dateien in php autoload, php nutzen von __autoload, php autoload class ablegen, namespace autoload variable klassen instanzierung, klassen automatisch einbinden autoload php

Alle Zeitangaben in WEZ +2. Es ist jetzt 01:31 Uhr.




Powered by vBulletin® Version 3.7.2 (Deutsch)
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
Aprilia-Forum, Aquaristik-Forum, Liebeskummer-Forum, Zierfisch-Forum, Geizkragen-Forum