PHP5-MVC-Framework: Fragen zum Aufbau

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Diese Klassen stammen alle, mit Ausnahme von Exception, von der Klasse Core ab, die Dinge wie Overloading etc bietet und wiederrum von Base abstammt welches einfach nur die Singleton-Funktion einbaut.

    Was genau bietet denn Core? Welches Overloading willst du in der Elternklasse einbauen? Magic Getter/Setter?
    Was ist mit 3rd Party Bibliotheken? Willst du die auch umschreiben, dass sie dem Core folgen?
    Ich würde keine gemeinsame Basisklasse einfügen, auch keine Library Basis Klasse, was weitere Fragen unten obsolete macht.
    Vor allem keinen globalen Singleton Support, den ja eigentlich nur ein Bruchteil der Klassen benötigt.

    Soll die Loader-Klasse welche ja die Klassen lädt als Library laufen oder als Core-File?

    Was genau macht deine Loader Klasse denn? Ich finde die Basisklassen wollten mit spl_autoload jeweils ihren eigenen Autoloader definieren.
    Was genau willst du denn in core überhaupt packen außer die index.php? Ich würde core schlichtweg entfernen und die index.php ins Root Directory verschieben ;)

    Sollen die Basis-Klassen der Models, Libraries, Controllers etc auch als Library laufen oder nicht?

    Libraries sind Klassen. Also ja, alles in den Library Ordner, siehe oben. Unterscheidung zwischen core und library verwirrt nur.

    Zum Pinnboard: Welchen Vorteil bringt das Pinnboard?

    Ansonsten würde ich noch über Sachen wie "Erweiterbarkeit durch Plugins", Paketupdates und Eventlistener nachdenken. Auch wie man das Caching implementiert.
    Und: Gibts ein htdocs Verzeichnis, welches dein "system" mitbringt. Bestehend aus JavaScript Basis Tools, Jquery, etc. ?

    Ein ganz nettes Framework zum Abschauen ist das Woltlab Community Framework.
    Einziger Kritikpunkt in meinen Augen ist das Model Konzept ohne umfangreiche Basisklasse.
    So sieht die Basis eine in meinen Augen guten Models aus: [wiki]Objektorientierung mit Models[/wiki]
    Mit PHP 5.3 Support wäre das sogar noch erheblich schlanker, aber dazu ist die Verbreitung leider noch zu gering :(
  • Da ich auch gerade dabei bin (um PHP zu erlernen) ein Framework zu erstellen gebe ich auch mal meine ideen/meinungnen preis

    mein aufbau derzeit sieht in etwa wie folgt aus:

    Quellcode

    1. %root%
    2. index.php - (enthält require_once() zu meinem main script)
    3. MyDirectory (zum testen falls das FW in einem subverzeichnis untergebracht wird)
    4. +- Framework
    5. | +- system (hier liegen alle files)
    6. | | +- classname (einzelne klassen, die aus mehreren dateien bestehen haben ein eigenes verzeichnis mit dem namen der klasse)
    7. | +- models (hier parke ich die models und templates für mein mvc)
    8. | +- templates (der name sagt alles - hier leigen auch gecachte inhalte)


    aber mal ne kleine performance frage (oder auch zwei oder drei):

    in meinem mainscript habe ich eine funktion

    PHP-Quellcode

    1. function force_mod($mod_name)
    2. {
    3. static $mods_loaded = array();
    4. if(!$mods_loaded[$mod_name])
    5. {
    6. $result =
    7. // FILEPATH.$mod_name ist nur die kurzfassung
    8. // im original wird aus dem mod_name ein file name erzeugt
    9. (file_exists(FILEPATH.$mod_file_name))
    10. ? require_once(FILEPATH.$mod_file_name)
    11. : false;
    12. }
    13. return $result;
    14. }
    Alles anzeigen

    diese funktion nutze ich in allen scripten um (bei bedarf mods nachzuladen wenn diese benötigt werden) anwendung ist dann wieder ganz einfach

    PHP-Quellcode

    1. $variable = (force_mod('diesermod') ? diesermod::diesefunkion() : NULL;

    ist das sinnvoll oder kostet das bei bedarf laden zuviel zeit ?

    für einige scripte habe ich konfigurationseinstellungen. diese habe ich jeweils in einem *.ini file gespeichert.
    ist es performance technisch sehr ungünstig wenn ich für einige mods diese einstellungen über parse_ini_file() importiere ?
    also derzeit habe ich bei 4 mods eine jeweils eigenen *.ini datei, wobei diese 4 mods nicht immer gebraucht werden
    z.b. bei meinem url dispatcher wird die *.ini nur benötigt wenn der request uri nicht eindeutig einen controller hergibt (das kann eigentlich nur dann passieren, wenn der user die request uri eingibt oder aus einem externen link stammt (also niemals aus einem generierten link heraus))
    auf meinem webserver (also net localhost) brauche ich bis zum aufruf meines controllers meist um 0,005 sekunden wenn ich meine scripte so aufrufe, dass alle mods geladen werden müssen.
    - ich weis, dass php 4 veraltet ist und ich lieber php 5 nutzen sollte
    - ich mache das ganze nicht nur um mein projekt zu erstellen, sondern um das ganze auch zu verstehen
    - wenn das ganze in php 4 funktioniert will ich es sauber nach php 5 migrieren
    - kurz gesagt ich WILL LERNEN VERSTEHEN und restlos BEGREIFEN wie das was ich möchte in php 4 / 5 / 6 umgesetzt werden soll
  • Hey,

    die nächsten zwei Wochen kann ich den Thread leider nur verfolgen und selber nicht viel schreiben. Ich hab gerade viel um die Ohren... Aber ich freu mich schon richtig auf die ganze Fachsimpelei...

    Ich werde mir ein Framework basteln, welches mehrere Seiten sehr einfach miteinander verknüpfen kann und diesen eine Administrative Oberfläche bietet (sofern sie sich an einen gewissen Standart halten). Damit verbunden ist eine User- und Rechteverwaltung.
    Den eigenen Webseitenentwicklern soll vorerst auch sehr viel Freifraum gelassen werden. Es sollen PHP-Grundkentnisse ausreichen, um eine kleine Seite in das Framework mit einzubinden. Dazu werden viele Funktionen bereit gestellt (keine Klassen), welches das erleichern.

    Gruß,
    Erasel
    My lovely mister singing club...
  • Nagut, ich denke ich muss das etwas detailierter erklären. Zurzeit habe ich schon einen gewissen Aufbau geplant, aber dieser ist bei weitem nicht perfekt, aber wäre lauffähig.
    Bisher habe ich ja auch erst Frameworks genutzt, aktiv dann auch nur Codeigniter. Ein Framework selbstgeschrieben habe ich auch noch nie, also habe ich ne Menge Fragen wie ich es am besten machen könnte.
    Ein Framework schreiben ist ja nicht schwer, ein gutes Framework zu schreiben dagegen sehr ^^

    Also zu meinem bisherigen Planungsstand:

    Ordnerstruktur

    system | Dateien des Frameworks, sollten vom Entwickler nie verändert werden
    - libraries | Die nativen Bibliotheken, z.B File-Library, Cache-Library, Log-Library, Database-Library etc
    - exceptions | Die nativen Exceptions des Frameworks, wie alles andere im system-Ordner auch sollten diese weder verändert noch gelöscht werden
    - core | Die Core-Dateien des Frameworks. Klassen und andere Dateien die für den Betrieb unbedingt nötig sind, aber auf keinen Fall erweitert, verändert, gelöscht, oder von Hand aufgerufen werden sollen. Deshalb passen sie auch nicht zu den Libraries
    - cache | Der Cache-Ordner des Frameworks. Ist nur im System-Ordner da ich noch keinen besseren Platz gefunden habe...
    - logs | Der Logs-Ordner, gleiches Problem wie bei Cache
    - database | Hier stecken die Datenbank-Treiber für z.B mysqli, mysql, etc drin
    app | Hier kommen alle Dateien der Anwendung hinein
    - controllers | Controller-Ordner eben. Die Controller können in Unterordner sortiert werden
    - libraries | Die eigenen Bibliotheken. Durch ein kleines System soll es so ganz einfach möglich sein eigene Libraries zu schreiben, und die nativen bestehenden zu erweitern ohne deren Dateien oder Klassen im system-Ordner ändern zu müssen
    - views | Die Views der Anwendung, Unterteilung in Unterordner soll auch hier möglich sein
    - resources | Hier kommen die Resourcen der Anwendung hinein, wie z.B...
    -- stylesheets | ...Stylesheets
    -- images | ...Bilder
    -- javascripts | ...Javascripts
    - config | Hier lagern alle Konfigurationsdateien. Jede Library hat ihre eigene Konfigurationsdatei, mehr soll es nicht geben
    - exceptions | Die Exceptions der Anwendung. Sie können die nativen Exceptions genauso wie es bei den Libraries möglich ist erweitern
    - models | Die Models. Unterteilung in ordner soll möglich sein...

    Klassen

    Zurzeit sieht der Klassenaufbau so aus, aber dieser muss denke ich komplett überarbeitet werden, da aber noch nichts vom Framework geschrieben ist sollte das ja kein Problem sein:

    Base | Singleton-Funktionen // Muss unbedingt geändert werden!
    - Die Klassen des "Kerns" des Frameworks
    - Core | Implementierung von Overloading (Magic setter & getter)
    -- Library | Basis-Klasse aller Libraries
    --- Log-Library
    --- Cache-Library
    --- etc.
    -- Controller | Basisklasse aller Controller
    --- Welcome-Controller
    --- etc.
    -- Model | Basisklasse aller Models
    --- User-Model
    --- etc.
    Exception | Basis-Klasse aller Exceptions // Wird nicht vom Framework deklariert, sondern ist ja bei PHP schon "dabei"
    - WasAuchImmerException

    Hoffe ich habe da nichts vergessen...
    Zurzeit ist alles ausser Exceptions Singleton. Nur: Braucht man da mehr? Controllers, Models, etc muss ja alles nicht mehrfach instanziert werden. Bei den Libraries könnte man darüber streiten, aber schliesslich fungieren auch diese nur als eine Art Kategorie für Funktionen die miteinander arbeiten.

    Restliches

    Nun zu meinen Fragen/Problemen/weiteren Erläuterungen:
    Die index.php legt einige Konstanten fest und ruft dann die system/core/init.php auf, welche alles initialisiert. Die Core-Klassen werden da geladen (Loader, Pinboard, Categories) und mit dem Loader dann die anfags erforderlichen Libraries (URL, Router, Request, File, Cache, Log etc).
    In meinem Framework wird eine Library oder ein Model geladen sobald es benötigt wird. Das ist jetzt recht kompliziert zu erklären:
    Alle Objekte der Libraries etc die die Loader-Klasse erzeugt, werden auf dem sogenannten Pinboard abgelegt. Dieses ist wiederum in Kategorien (eigentlich Objekte der Klasse Category, eine Klasse für "leere" Objekte bzw um eben DInge darauf abzulegen) eingeteilt.
    Es gibt als Kategorien libraries, models, controllers, views (Jede View bekommt ein eigenes Objekt über welches man Daten zur View hinzufügen kann). So werden die Objekte der Libraries etc also nicht direkt auf dem Pinboard abgelegt sondern in einem Category-Objekt vonwelchem ein Objekt in einer Instanzvariable der Pinboard-Klasse abgelegt ist. Die Category-Klasse stellt nun eben magische setter und getter zur Verfügung welche eine Klasse automatisch von der Loader-Klasse laden lassen, wenn von dieser Klasse noch kein Objekt existiert.
    Nagut: Weil die Pinboard-Klasse singleton wie eigentlich jede Klasse im Framework ist, kann man einfach von überall auf alle geladenen Libraries etc zugreifen. Durch eine kleine "Umleitung" über magische setter und getter in der Core-Klasse, welchen ja allen Basis-Klassen von Libraries etc. zu Grunde liegt , wird die Instanzvariable mit dem Objekt des Pinboards umgangen: Angenommen wir sind jetzt in einem Controller oder eine anderen Klasse welche mit der Core-Klasse verwandt ist, können wir auf eine Library oder ähnlich so zugreifen: $this->libraries->cache->write(); statt, ohne Umleitung, $this->ff_pinboard->libraries->cache->write();

    Das war gerade warscheinlich zu kompliziert und ihr habt mindestens 90% nicht verstanden denke ich, aber fragt einfach wenn ihr Fragen habt ^^

    Wenn ihrs verstanden habt: Was kann man besser machen? (man kann garantiert viel besser machen...)
    Soll die Loader-Klasse eine Library sein? Da ich ja auch Haupt-Klassen für jede Klassen-Art (Controller, Libraries, Models...) anbieten will die der Entwickler bearbeiten kann: Soll ich einfach in den jeweils entsprechenden Ordner eine z.B main.library.php tun, von deren beinhaltenden Klasse dann alle Libraries abstammen? Wäre meiner Meinung nach die beste Lösung...

    greez

    bitsnack

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von bitsnack ()

  • Na gut, das Pinnboard bietet also eine einfachere Syntax um ein Singleton Objekt zu instanziieren.
    Die Category Klasse managed dabei das Eager Loading, lädt die Instanz also nur falls benötigt.

    Damit Pinnboard/Category nun als Factory alle deine Libraries auf die gleiche Art instantiieren können, sollten sie eine gemeinsame Basisklasse (abstrakt) haben.
    Mehr dazu hier: [wikipedia]Fabrikmethode[/wikipedia]
  • Nein.
    Das Pinboard ist einfach ein Objekt in dem 4 weitere Objekte der Klasse Category lagern. In diesen Category-Objekten werden dann die Objekte der geladenen Libraries oder für welche Kategorie von Klasse das Category-Objekt auch zuständig ist.
    Falls ein Objekt vom Category-Objekt angefordert wird welches nicht existiert wird die Loader-Klasse bemüht um die Klasse zu laden.
    Das Pinboard ist dann wieder als Instanz-Variable in jeder Library, in jedem Model und Controller (wird von der Basisklasse diese beim instanzieren erstellt). Das Pinboard ist deshalb auch Singleton, da ja immer das gleiche Objekt vom Pinboard in den Klassen sein soll.
    PS: Das ganze ist also eher Lazy-Loading...

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von bitsnack ()

  • bin mal auf 'readonly' status, da ich für mein FW gerade ein an subversaion angelehntes archivsystem erstelle und daher meine monitore alle zum coden brauche :)
    - ich weis, dass php 4 veraltet ist und ich lieber php 5 nutzen sollte
    - ich mache das ganze nicht nur um mein projekt zu erstellen, sondern um das ganze auch zu verstehen
    - wenn das ganze in php 4 funktioniert will ich es sauber nach php 5 migrieren
    - kurz gesagt ich WILL LERNEN VERSTEHEN und restlos BEGREIFEN wie das was ich möchte in php 4 / 5 / 6 umgesetzt werden soll
  • Aber wie kann ich sonst Kategorien machen? Also dass eine Bibliothek (nur) so aufrufbar ist: $this->libraries->foo->bar();
    Ich kann ja nicht einfach für jede Kategorie das Pinboard/Dashboard/wie mans auch nennen will laden. Dann wärs ja kein Singleton mehr.
    Klar wäre es möglich zu schauen ob die Kategorie schon existiert und diese bei bedarf zu laden. Aber eine Library soll man auch eine art bookmarken können, damit sie direkt über $this->foo->bar(); zugänglich ist.
    Zwischen $this-> und foo->... ist ja theoretisch noch die Instanzvariable mit dem Objekt des Pinboards, aber diese wird mit _get und _set übergangen.
    $this->var leitet also immer auf das Pinboard weiter.

    Die wichtigste Frage für mich ist bisher einfach welche Klassen ich als Library laufen lasse und welche nicht.

    Eine Frage am Rande hab ich dann noch: Models.
    Welche Variante ist besser:

    $usermodel->createUser($username, $password, $email, ...);
    $usermodel->deleteUser($username);

    oder

    $user = new User($username, $password, $email);
    $user->save();
    $user = new User($username);
    $user->delete();

    Was ist in einem Framework besser? Welches ist verbreiteter und wie kann man das verbessern?
  • kannst du deine category objects nicht so:

    PHP-Quellcode

    1. $this->foo =&$this;
    2. $this->bar =&$this;

    definieren ?
    in meiner php4 factory klappt das einwandfrei

    PHP-Quellcode

    1. // ...
    2. function __construct()
    3. {
    4. $this->load =& $this;
    5. }
    6. function libraries($classname)
    7. {
    8. // ...
    9. }
    10. //...
    11. // irgendwo später :
    12. $object->load->libraries('newclass');
    13. // ...
    14. // wieder irgendwo später
    15. $object->newclass->diesefunction();
    Alles anzeigen


    müsstest das dann nur so anpassen, dass $this->$category =& $this immer nur dann angelegt wird, wenn die category erstellt wird.

    denke zumindest dass das auch klappen sollte
    - ich weis, dass php 4 veraltet ist und ich lieber php 5 nutzen sollte
    - ich mache das ganze nicht nur um mein projekt zu erstellen, sondern um das ganze auch zu verstehen
    - wenn das ganze in php 4 funktioniert will ich es sauber nach php 5 migrieren
    - kurz gesagt ich WILL LERNEN VERSTEHEN und restlos BEGREIFEN wie das was ich möchte in php 4 / 5 / 6 umgesetzt werden soll
  • bitsnack schrieb:

    Eine Frage am Rande hab ich dann noch: Models.
    Welche Variante ist besser:

    $usermodel->createUser($username, $password, $email, ...);
    $usermodel->deleteUser($username);

    oder

    $user = new User($username, $password, $email);
    $user->save();
    $user = new User($username);
    $user->delete();

    Was ist in einem Framework besser? Welches ist verbreiteter und wie kann man das verbessern?



    Ich würde die zweite Variante nehmen, jedoch beim Konstruktor nicht alle Werte übergeben

    $usr = new UserModel(); // neuer Benutzer
    $usr = new UserModel($usrId) // bestimmter Benutzer anhand ID oder Name
    $usr->email = "...."; // __set methode
    echo $usr->password; // __get methode

    $usr->save();
    $usr->delete();
    ...

    wenn du auf __get und __set verzichten möchtest, kannst du natürlich auch methoden wie $usr->getEmail(); machen. Falls du zu faul bist alle Methoden selber zu schreiben und das ganze dynamisch halten willst, kannst du hierzu auch auf die __call Methode zurück greifen.

    LG Gregor
  • Ich fasse nochmal zusammen..

    Angenommen wir sind jetzt in einem Controller oder eine anderen Klasse welche mit der Core-Klasse verwandt ist, können wir auf eine Library oder ähnlich so zugreifen: $this->libraries->cache->write(); statt, ohne Umleitung, $this->ff_pinboard->libraries->cache->write();


    Das Pinboard ist dann wieder als Instanz-Variable in jeder Library, in jedem Model und Controller (wird von der Basisklasse diese beim instanzieren erstellt). Das Pinboard ist deshalb auch Singleton, da ja immer das gleiche Objekt vom Pinboard in den Klassen sein soll.


    Aber wie kann ich sonst Kategorien machen? Also dass eine Bibliothek (nur) so aufrufbar ist: $this->libraries->foo->bar();


    Warum überhaupt als Membervariable? Und warum über ein Dashboard? Warum nicht einfach so:

    Quellcode

    1. Registry::load('foo')->bar()

    Keine unnötige Kopplung, keine magische Methoden, keine Komplexität.

    Von mir aus auch mit magischen statisch methoden (ab php 5.3) und einer noch kürzeren, wenngleich für mich nicht unbedingt intuitiveren syntax:

    Quellcode

    1. Registry::foo()->bar()


    Zur Syntax mit den Models zitiere ich nochmal meinen Wiki Artikel: [wiki]Objektorientierung mit Models[/wiki]
    Die Syntax ist sehr verbreitet, nicht nur bei PHP Frameworks, auch bei Rails, Django, etc.

    @Szabo bzw new UserModel($usrId)
    ich weiß nicht ob du mit dem Konstruktor das Objekt aus der Datenbank laden willst... manche Frameworks machen das. Ich würde jedoch dafür statische Methoden benutzen, da du über Konstrukor immer eine Instanz erzeugst, also keine eindeutige "Singleton" mehr erzeugen kannst.
  • In CodeIgniter ist ein Model auch Singleton und wird auch mit $this->user_model->createUser(); verwendet. Denke ich werde das bei meinem Framework auch machen.
    Klar könnte man ein Objekt pro Benutzer erstellen, aber ich denke da könnte man den Überblick über die Objekte verlieren.

    Zum Dashboard: Es soll als Zentrale Ablage für Objekte dienen. Und zu den Categories: Diese sollen eben als Kategorien für die Objekte dienen. Anders kann man genau das ja nicht realisieren!?

    Der Loader (die Factory) wird also zu den Libraries gehen, Das Pinboard und Categories nicht. Evtl finde ich eine Möglichkeit Kategorien auch ohne eine extra Klasse so zu erzeugen, dass sie auch andere Methoden als das Pinboard haben.

    Model, Library und Controller werden Abstrakte Klassen sein, welche sich im jeweiligen Ordner in app/ befinden.
    So kann man Sie leicht erweitern und ich benötige da kein weiteres System.
    In den Klassen steht ja ohnehin nichts, ausser man passt sie eben an.

    Damit wäre das Thema eigentlich geklärt, ausser ihr hättet noch Tipps welche ich beachten sollte oder irgendwelche Design Patterns welche ich verwenden/unterbringen könnte.

    Vielen Dank schonmal!