XHTMLforum

XHTMLforum (http://xhtmlforum.de/index.php)
-   Serveradministration und serverseitige Scripte (http://xhtmlforum.de/forumdisplay.php?f=80)
-   -   PHP, OOP und Array Übergabe (http://xhtmlforum.de/showthread.php?t=63223)

laborix 12.12.2010 15:30

PHP, OOP und Array Übergabe
 
Hallo miteinander,

eine theoretische Frage, die ich noch nicht verstehe, die mich aber sehr interessiert.

Die Klasse:
Code:

class ConfigPanel {

  public function readconfigfile(array $readconfig) {

  }

  public function showconfigfile(array $showconfig) {

  }

  public function writeconfigfile(array $writeconfig) {

  }

}

Der Aufruf in configpanel.php:
Code:

require_once("class.contactconfig.php");

$debugarray = array();
$debugconfigpanel = new ConfigPanel();
$debugarray = $debugconfigpanel->readconfigfile($debugarray);
$debugarray = $debugconfigpanel->showconfigfile($debugarray);
$debugarray = $debugconfigpanel->writeconfigfile($debugarray);

Zur Frage:
Kann ich für alle drei Funktionen innerhalb der Klasse den gleichen Array Namen angeben?
Code:

class ConfigPanel {

  public function readconfigfile(array $config) {

  }

  public function showconfigfile(array $config) {

  }

  public function writeconfigfile(array $config) {

  }

}

Weiss das einer von euch und kann mir das irgendwie verständlich machen ob das geht oder nicht?

Hinweis:
Zur Zeit arbeite ich mit drei verschiedenen Array Namen und es funktioniert. Ich bekomme auch keinen Fehler oder Hinweis, wenn ich mit
Code:

error_reporting (E_ALL | E_STRICT);
arbeite. Ich stecke hier noch etwas in den Anfängen :roll:

Danke

stravid 12.12.2010 23:27

Ja das geht.

Du kannst ihnen den gleichen Namen geben da es Funktionsparameter sind und sie deswegen nichts miteinander zu tun haben.

Praktikant 13.12.2010 01:45

Funktionsparameter sind nur in den Funktionen verfügbar in denen sie definiert sind. So sind deine 3 Arrays auch nur in den Funktionen verfügbar, sie wissen garnicht dass in einer anderen Funktion eine Variable gleichen Namens existiert.

Würdest du jedoch eine Klassenvariable daraus machen ($this->array), dann wäre diese in jeder Funktion das selbe Array. Ändert dann eine Funktion etwas am Inhalt, z.B. durch hinzufügen oder löschen, so wissen alle andere Funktionen gleich von der Änderung und arbeiten mit dem gleichen Datenbestand. Es kommt immer darauf an wofür es gebraucht wird.

laborix 13.12.2010 20:30

Danke euch beiden, das habe ich nicht gewusst.

Empfiehlt es sich allen internen Funktionen den gleichen Übergabe Parameter zu geben?

Praktikant 13.12.2010 22:15

Es empfiehlt sich logische Namen zu verwenden. Wie die heißen ist egal, ob es die selben meistens auch. Ich arbeite nicht gerne mit Klassenvariablen, die wollen so gerne initialisiert werden. Ich übergebe Parameter gerne in die Funktionen beim Aufruf. Wenn ich Objekte übergeben muss, dann kommen die in eine Klassenvariable. Aber sonst verwende ich die selten.

mantiz 14.12.2010 00:06

Zitat:

Zitat von Praktikant (Beitrag 482596)
Es empfiehlt sich logische Namen zu verwenden. Wie die heißen ist egal, ob es die selben meistens auch. Ich arbeite nicht gerne mit Klassenvariablen, die wollen so gerne initialisiert werden. Ich übergebe Parameter gerne in die Funktionen beim Aufruf. Wenn ich Objekte übergeben muss, dann kommen die in eine Klassenvariable. Aber sonst verwende ich die selten.

Heisst das, dass Du Klassen (Objekte) lediglich als Wrapper (Namespace) für Deine Funktionen nutzt?

Ich komme bei objektorientierter Programmierung nicht ohne Klassenvariablen bzw. Attributen aus, oder verstehe ich Dich hier falsch?

Praktikant 14.12.2010 01:16

Zitat:

Zitat von mantiz (Beitrag 482655)
Heisst das, dass Du Klassen (Objekte) lediglich als Wrapper (Namespace) für Deine Funktionen nutzt?

Ich komme bei objektorientierter Programmierung nicht ohne Klassenvariablen bzw. Attributen aus, oder verstehe ich Dich hier falsch?

Nein, das hast du richtig verstanden. So Sachen wir Benutzer ID oder sowas speicher ich auch in Klassenvariablen, aber das war es dann meistens schon. Ich versuche immer so viel möglich zu vererben, bis ich die Möglichkeiten des Vererbens sprenge. Das muss man dann zwar alles irgendwo aufschreiben, aber das ist ja machbar :mrgreen:

Allerdings ändert sich das in regelmäßigen Abständen. Mit kleinen Projekten probiere ich immer wieder andere Wege aus, den für mich Perfekten habe ich leider noch nicht gefunden.

mantiz 14.12.2010 10:27

OK, hatte mich nur mal interessiert.

Ich war selbst auch lange auf der Suche, dann mal viel Erfolg. ;)

Praktikant 14.12.2010 11:27

Wie machst du es denn? Wie gehst du mit Vererbung, Klassenvariablen und so weiter um?
Was überginst du eher an Klassenvariablen, was eher als Funktionsparameter?

Vielleicht kann ich bei dir ja was lernen :mrgreen:

mantiz 14.12.2010 11:56

Naja, ich habe da keine bestimmte Regel oder sowas.

Ich versuche sämtliche Variablen so lokal wie möglich zu halten und sämtliche Werte, welche Konfiguration oder Resourcen oder ähnliches sind im Objekt bzw. der Klasse zu speichern.

Als Beispiel hier mal die Attribute meines abstrakten Controllers:
PHP-Code:

protected $acl;
protected 
$auth;
protected 
$authAdapters = array();
protected 
$config;
protected 
$controllerKey;
protected 
$dbConnections = array();
protected 
$frontcontroller;
protected 
$messages = array();
protected 
$models = array();
protected 
$refClass;
protected 
$request;
protected 
$response;
protected 
$router;
protected 
$session;
protected 
$view

Hier die des Frontcontrollers welcher natürlich von AbstractController erbt:
PHP-Code:

protected $controllers = array();
protected 
$layoutEnabled true;
protected 
$preDispatchFilter;
protected 
$postDispatchFilter

Nun werden natürlich nicht sämtliche Attribute ständig verwendet, am Beispiel des Request-Objektes einmal verdeutlicht:

Das Request-Objekt, sowie sämtliche Controller, werden (standardmäßig) im Frontcontroller erstellt, dabei wird den Controllern die Instanz des Frontcontrollers übergeben.

Nun sieht die Methode getRequest() im AbstractController folgendermaßen aus (hier vereinfacht):
PHP-Code:

public function getRequest() {
    if (
$this->request !== null) {
        return 
$this->request;
    }
    
    if ((
$fc $this->getFrontcontroller()) !== null) {
        if (
$fc !== $this) { // avoid recursion
            
return $fc->getRequest();
        }
    }
    
    return 
null;


Auf die Art habe ich sämtliche Getter implementiert, so dass im Controller ein simples "$this->getRequest()" ausreicht, um an das richtige Objekt zu gelangen, ebenso wäre es aber möglich bestimmten Controllern ein anderes Request-Objekt zu geben.
Im Detail wäre es wohl zu viel alles zu erklären, hier nur mal als Idee.

Hier kommen imo nur Attribute in Frage, alles andere wäre unnötig kompliziert und redundant.

Ein anderes Beispiel wäre meine DbTable-Klasse, wo ich ein wenig von Zend abgeschaut habe, hier habe ich die Attribute:
PHP-Code:

protected $dbConnection;
protected 
$name;
protected 
$primary

In $dbConnection wird die aktuelle Datenbankverbindung gespeichert (inkl. Datenbank), $name enthält den Tabellennamen und $primary den Namen der Spalte, welche den Primärschlüssel angibt.
So kann man so schön kurze, sowie unabhängige Methoden wie z.B.:
PHP-Code:

public function find($primary) {
    return 
$this->fetch(array($this->primary => $primary));


schreiben, also z.B.
PHP-Code:

$commentModel = new DbTable($dbConnection'comments''id');
// ...
$comment $commentModel->find(1); 

anstelle von
PHP-Code:

$commentModel = new DbTable($dbConnection'comments''id');
// ...
$comment $commentModel->fetch(array('id' => 1)); 

Der Code wird imo generischer und besser wartbar.

Dazu sollte ich aber noch sagen, dass bei mir die Angaben zum Tabellennamen und Primärschlüssel ebensowenig im Code stehen (das habe ich hier nur kurz so gemacht), sondern per Config gesetzt werden.

So kann der Primärschlüssel z.B. von "id" nach "commentId" geändert werden, die Änderung wird in der Config-Datei vorgenommen und man ist fertig. ;)

Praktikant 14.12.2010 19:19

Das ist sicherlich ein guter Weg, darüber werde ich einmal nachdenken, danke :)

Ich habe aber noch nicht so ganz verstanden warum du den Primary der Tabelle speicherst. Ich speicher immer nur den Namen der Tabelle in der Konfigurationsdatei und frage dann ab. Was machst du denn, wenn du mal ein Feld abfragen musst, welches nicht Primary ist oder du einen Zusammengesetzen Primary hast?

mantiz 14.12.2010 20:24

Wenn ich ehrlich bin, dann ist das ganze noch in der Entwicklung und ich würde es als pre-Alpha einstufen, das vielleicht noch ergänzend. ;)

Den Primary speichere ich aus Faulheit, ganz einfach, ist immer gut, wenn man als Programmierer zu einem gewissen Grad faul ist. :)

Die einfache (soll heißen normale) fetch-Methode bekommt als ersten Parameter eine Bedingung als Array übergeben, wenn ich aber bereits weiß, dass die Bedingung lediglich auf den Primärschlüssel filtert, wieso sollte ich den Primärschlüssel jedes Mal mit angeben und ihn so über den Code verteilen?

Für mich bedeutet das: Zentralisierung.

Wie bereits erwähnt lässt sich so eine Methode "find($primary)" schreiben, welche mir einen Datensatz zurückliefert, der im Primärschlüssel den Wert von $primary besitzt, oder aber $primary ist ein Array, dann werden sämtliche Datensätze mit den entsprechenden Primärschlüsseln zurückgeliefert.
Mir ist bei meinen Codes aufgefallen, dass ich sehr häufig anhand der Primärschlüssel selektiere, das muss aber längst nicht bei jedem so sein.

Eine weitere Methode von DbTable ist z.B. "update($primary, array $data)", welche einen bzw. mehrere Datensätze entsprechend der in $data angegebenen Felder aktualisiert.

Wie gesagt, so lässt sich der Primärschlüssel fix ändern und da die Klasse teil eines Frameworks ist woran ich derzeit arbeite sollte diese auch so flexibel wie möglich sein.

Ansonsten müsste ich die Bedingung immer vollständig mit angeben, was bei mir z.B. so aussehen würde:
PHP-Code:

$commentModel->update(array('id' => 1), array('published' => 1)); 

Warum aber ständig "array('id' => 1)" schreiben, wenn "1" reichen kann? :)

Zusätzlich gibt es aber noch eine Methode "updateByCondition", wo man eine beliebige Bedingung angeben kann, es ist also nicht auf den Primärschlüssel beschränkt.

Wie gesagt ist die Klasse noch nicht fertig, aber falls bis dato komplizierte Queries benötigt werden besitzt die Klasse "DbConnection" bzw. "MysqlDbConnection" eine Methode "query", welche direkt ein SQL-Query entgegen nimmt und ausführt, darüber hat man dann sämtliche Freiheiten.

Zur Info:
DbConnection bzw. deren Erben sind bei mir die Datenbank-Wrapper um Funktionen wie "mysql_query" und Konsorten zu kapseln.

Aber wie gesagt, das muss nicht bei jedem so passen.

Dazu kommt, dass ich mich in letzter Zeit ein wenig mit Inversion-of-control beschäftigt habe, was wohl generell bei Frameworks sehr beliebt ist.
Im Prinzip geht es dabei darum, dass die Klassen bzw. Objekte sich die Daten, die sich brauchen, nicht selbst besorgen, sondern diese von "außen" (häufig automatisch, bei mir aber nicht) zugewiesen bekommen, das macht es aber zwangsweise nötig, dass diese lokal im Zielobjekt gespeichert werden.

Vorteil des ganzen ist, dass die Klasse weniger Abhängigkeiten besitzt und somit, so die Hoffnung, vielseitiger und einfacher eingesetzt werden kann.

Z.B. werden bei mir die Datenbankverbindungen automatisch vom Frontcontroller per lazy-loading anhand der Config erstellt und verbunden, ein (normaler) Controller muss sich zu keiner Zeit darum kümmern.

Aber es wäre denkbar, dass ich nur einen einzigen bestimmten Controller aus dem Framework für eine kleine Anwendung verwenden will.
Wenn dieser Controller z.B. lediglich eine DbConnection von außen erwartet, dann kann ich diese 2 bzw. 3 Klassen aus dem Framework auskoppeln und einzeln verwenden:
PHP-Code:

require('lib/DbConnection.php');
require(
'lib/MysqlDbConnection.php');
require(
'lib/SimpleController.php');

$dbConnection = new MysqlDbConnection();
$dbConnection->getConfig()
   ->
set('hostname''localhost')
   ->
set('username''...')
   ->
set('password''...')
   ->
set('database''...');

$controller = new SimpleController();
$controller->setDbConnection($dbConnection);
$controller->doSomething(); 

Wenn der Controller sich die DbConnection beispielsweise nur automatisch vom Frontcontroller holen würde und ihm nicht eine eigene zugewiesen werden könnte, müsste man u.U. recht viele Abhängigkeiten erfüllen, bis die Klasse vernünftig verwendet werden könnte.

Naja, meine Erklärung hinkt ein wenig, aber ich hoffe es wird so einigermaßen klar welche Gedanken dabei eine Rolle spielen.

laborix 14.12.2010 20:58

Hey :D , dass war mein Thread :lol:

Spass beiseite, cool, da ich noch in den Anfängen stecke. kann ich hier jetzt echt was lernen. Nicht aufhören, ok?

mantiz 15.12.2010 00:04

Oh sorry. ;)

Ich habe mich selbst auch (besonders beim zweiten Post) ziemlich erschrocken wie lang die Antworten geworden sind, war so nicht beabsichtigt.

Vielleicht sollte ich auch noch dazu sagen, dass ich mir im Vorfeld besonders die Frameworks Zend, CakePHP und APF angesehen habe und mich zwangsweise auch mit dem Java-Framework Apache Tapestry beschäftige.

Ich habe mir das alles also nicht komplett selbst ausgedacht, sondern versucht mein Verständnis von der ganzen Materie umzusetzen.

Ich kann nur empfehlen sich mal ein paar Frameworks anzusehen, ich habe das Gefühl, dass ich dabei sehr viel gelernt habe.

Jetzt ist das schon wieder so lang geworden ... :shock:

laborix 15.12.2010 20:46

Zitat:

Zitat von mantiz (Beitrag 482965)
Oh sorry. ;) ...

Kein Problem :D

Sequenziell Programmieren mit PHP war bisher nicht allzu schwer, aber mit OOP ist das ganze in Bezug auf Abhängigkeiten von Klassen und Funktionen nicht so einfach.

Vor vielen Jahren habe ich Job bedingt aufgehört mit dem Programmieren (Cobol/Assembler/C). Inzwischen werde ich im Beruf mit vielen Webinterfaces für Server aller Arten konfrontiert, die teilweise HTML-, Java- und PHP-Module beinhalten. Es wird Zeit mich damit etwas tiefer auseinander zu setzen :)

mantiz 15.12.2010 21:25

Zitat:

Zitat von laborix (Beitrag 483089)
Sequenziell Programmieren mit PHP war bisher nicht allzu schwer, aber mit OOP ist das ganze in Bezug auf Abhängigkeiten von Klassen und Funktionen nicht so einfach.

Das kenne ich nur zu gut. ;)

Zitat:

Zitat von laborix (Beitrag 483089)
Vor vielen Jahren habe ich Job bedingt aufgehört mit dem Programmieren (Cobol/Assembler/C). Inzwischen werde ich im Beruf mit vielen Webinterfaces für Server aller Arten konfrontiert, die teilweise HTML-, Java- und PHP-Module beinhalten. Es wird Zeit mich damit etwas tiefer auseinander zu setzen :)

Je nachdem wieviel Zeit und Interesse vorhanden ist, kann ich nur dazu raten sich einmal verschiedene Frameworks anzusehen und zu schauen, wie dort verschiedene Dinge gelöst wurden, war für mich aber ein schwerer Weg auf dem ich zwischenzeitlich alles, was ich bis dato gelernt hatte in Frage gestellt habe. :)
Jedes hat so seine Stärken und Schwächen.
Beim Verständnis der Frameworks und der darin umgesetzten Patterns hat mir das Buch PHP Design Patterns sehr geholfen.

David 21.12.2010 12:29

Wenn ich mich mal fragend einklinken darf: @Mantiz, wie realisierst du (bzw. wie hast du vor zu realisieren) joins? Willst Du mehrere Tabellen-Objekte miteinander verknüpfen, oder machst Du sowas händisch, also über eine normale SQL-Abfrage?

Praktikant 21.12.2010 12:36

Entschuldige, dass ich so lange nichts habe von mir hören lassen. Ich habe deinen Text mehrfach gelesen und mir Gedanken gemacht. Ich denke, ich werde mir viel bei dir abschauen und mich ebenfalls mehr mit Frameworks auseinander setzen :) Danke für den Tipp mit dem Buch.

Ich habe aber verstanden worauf du mit deinen Gedanken hin willst und gemerkt, dass es Sinn macht das ganze so aufzubauen. Danke für deine Beschreibung.

Zitat:

Zitat von David (Beitrag 483539)
Wenn ich mich mal fragend einklinken darf: @Mantiz, wie realisierst du (bzw. wie hast du vor zu realisieren) joins? Willst Du mehrere Tabellen-Objekte miteinander verknüpfen, oder machst Du sowas händisch, also über eine normale SQL-Abfrage?

Ich denke so etwas realisiert er über die Methode query, welche ein MySQL-Anweisung direkt ausführt.

mantiz 21.12.2010 14:00

Zitat:

Zitat von David (Beitrag 483539)
Wenn ich mich mal fragend einklinken darf: @Mantiz, wie realisierst du (bzw. wie hast du vor zu realisieren) joins? Willst Du mehrere Tabellen-Objekte miteinander verknüpfen, oder machst Du sowas händisch, also über eine normale SQL-Abfrage?

Ja, momentan mache ich sowas quasi händisch.
Die Klasse DbTable unterstützt keine Joins, soll halt eine simple Model-Klasse sein, die genau einer Datenbank-Tabelle entspricht.
Aber man könnte eine Model-Klasse DbJoinedTables schreiben, die das erledigen würde.
Zum Aufbauen von Queries habe ich eine Klasse DbQuery, womit ich das relativ simpel machen kann.

Beispiel:
PHP-Code:

$list $dbConnection->select()
        ->
from('table1 t1')
        ->
join('table2 t2''t2.id .''t1.id''left')
        ->
getList(); 

Zur Info:
DbConnection::select() liefert eine vorkonfigurierte Instanz meiner DbQuery-Klasse zurück.
Der Punkt bei "t2.id ." gibt an, dass es sich bei dem Wert "t1.id" um eine Tabellen-Spalte handelt, das ist für das Escapen wichtig.
Bei Mysql wird dadurch aus "t1.id" "`t1`.`id`", ansonsten würde es als String behandelt werden.

Welche Tabellen wie gejoined werden sollen könnte man per Attribute vorsehen und das Query anhand dessen aufbauen.

Sollten noch kompliziertere Queries benötigt werden, dann muss ich erstmal in den sauren Apfel beißen und das Query per Hand zusammenbauen.

Ich hatte vor einger Zeit auch mal versucht einen OR-Mapper zu schreiben, bin aber kläglich gescheitert, ist nicht zu unterschätzen.
Evtl. greife ich das irgendwann nochmal auf, aber bestehende OR-Mapper sind nicht umsonst so umfangreich, da gibt es einiges zu beachten was mir momentan einfach zu komplex ist.
Erstmal brauche ich jetzt eine hoffentlich vernünftige Grundstruktur. :)

Zitat:

Zitat von Praktikant (Beitrag 483540)
Entschuldige, dass ich so lange nichts habe von mir hören lassen. Ich habe deinen Text mehrfach gelesen und mir Gedanken gemacht.

Kein Problem. ;)

Zitat:

Zitat von Praktikant (Beitrag 483540)
Ich denke, ich werde mir viel bei dir abschauen und mich ebenfalls mehr mit Frameworks auseinander setzen :) Danke für den Tipp mit dem Buch.

Im Grunde schaust Du ja nicht bei mir ab, sondern bei den ganzen Frameworks. :)
Sehr viele Ansätze (zumindest was grundsätzliches betrifft) habe ich ja aus den anderen Frameworks, nicht dass der Eindruck entsteht ich hätte mir das alles selbst ausgedacht, ich kann's nicht oft genug sagen.
Vor allem die Unterteilung in Bootstrap-Datei (bei mir die index.php), Router, Frontcontroller, (Application-)Controller habe ich aus dem Zend-Framework, wobei Zend im Frontcontroller noch einen extra Dispatcher für den Aufruf (die Aufrufe) von Controllern verwendet. Dies macht ebenfalls Sinn, da Zend hier eine Controller-Chain einsetzt, welche es erlaubt mehrere Controller-Actions verkettet auszuführen.
Für mich habe ich dafür aber keine Notwendigkeit gesehen, also hab' ich darauf verzichtet. :)

Zitat:

Zitat von Praktikant (Beitrag 483540)
Ich habe aber verstanden worauf du mit deinen Gedanken hin willst und gemerkt, dass es Sinn macht das ganze so aufzubauen. Danke für deine Beschreibung.

Kein Problem, am Ende bin ich mit der ganzen Sache auch noch nicht. Ich muss jetzt erstmal ein paar (kleinere) Projekte damit umsetzen, um zu sehen, wie sich das ganze in der Praxis verhält, oft ergeben sich dann Anforderungen, wo man vorher noch nicht dran gedacht hat.
Ich hoffe es ändert sich nicht mehr all zu viel. :D

Praktikant 21.12.2010 14:30

Aber du hast mich auf die Idee gebracht, dort wirklich mal reinzuschauen. Sonst hätte ich das wahrscheinlich nie gemacht :p

Zitat:

Zitat von mantiz (Beitrag 483566)
Kein Problem, am Ende bin ich mit der ganzen Sache auch noch nicht. Ich muss jetzt erstmal ein paar (kleinere) Projekte damit umsetzen, um zu sehen, wie sich das ganze in der Praxis verhält, oft ergeben sich dann Anforderungen, wo man vorher noch nicht dran gedacht hat.
Ich hoffe es ändert sich nicht mehr all zu viel. :D

Wie lange hast du ungefähr gebraucht bis zu deinem jetzigen Stand. Wie nah am "Ende" bist du mittlerweile?

David 21.12.2010 14:39

Interessanter Ansatz. Allerdings frage ich mich immer, ob das ganze überhaupt noch vertretbar ist aus sicht der Leistungsfähigkeit. Ich mein, man muss die Attribute erst umständlich zu einer Syntaktisch korrekten Query zusammenbauen, die schlussendlich vom SQL-Server wieder geparst wird. Außerdem müssen die ganzen Objekte ja auch zwischengespeichert werden. Ich kann mir das aber auch nur einbilden.

Ist auf jedenfall schöner als wenn man jeden einzelen Query selbst zusammenschraubt.

mantiz 21.12.2010 15:28

Zitat:

Zitat von Praktikant (Beitrag 483569)
Wie lange hast du ungefähr gebraucht bis zu deinem jetzigen Stand. Wie nah am "Ende" bist du mittlerweile?

Am Framework an sich habe ich die letzten 2 Monate gearbeitet, allerdings nicht am Stück. Vorher hatte ich bereits einen Versuch mit nahezu identischen Klassen wie aus dem Buch "PHP Design Patterns" unternommen, habe dann aber festgestellt, dass man Patterns nicht "einfach so" umsetzen sollte.
Und natürlich habe ich einige Klassen, z.B. DbQuery und Template bereits vorher schon gehabt und habe diese nur auf's Framework angepasst, sonst hätte ich entschieden länger gebraucht, da gerade die beiden Klassen für mich in der Entwicklung sehr zeitaufwendig waren.
Am Ende werde ich wohl nie sein, da das Framework eine Basis darstellen soll und sämtliche Module, die ich später mal brauche nach Möglichkeit integriert werden sollen.
Momentan baue ich 3 Seiten damit auf, eine einfache Website mit Kontaktformular, eine Bildergalerie und einen Shop.
Ich denke, wenn ich damit durch bin kann ich auf 1.0-beta gehen.
Ich neige aber dazu auch in fortgeschrittenen Zyklen Schnittstellen auf einmal über den Haufen zu werfen, so dass ich mir das gut überlegen muss. :)
Ich weiß auch noch nicht, ob ich das mal veröffentlichen will oder es auch nur mein kleines Werkzeug bleibt.

Zitat:

Zitat von David (Beitrag 483570)
Interessanter Ansatz. Allerdings frage ich mich immer, ob das ganze überhaupt noch vertretbar ist aus sicht der Leistungsfähigkeit. Ich mein, man muss die Attribute erst umständlich zu einer Syntaktisch korrekten Query zusammenbauen, die schlussendlich vom SQL-Server wieder geparst wird. Außerdem müssen die ganzen Objekte ja auch zwischengespeichert werden. Ich kann mir das aber auch nur einbilden.

Das stimmt auf jeden Fall, Performance geht verloren, aber das ist klar, anders geht's halt nicht. :)
Für mich besteht der Vorteil darin, dass ich mich nicht um so Dinge wie das quoten der Spalten oder escapen der Werte kümmern muss, weil das von DbQuery automatisch vorgenommen wird, das hilft schonmal bei der Übersichtlichkeit.
Zusätzlich bleibt man zu einem gewissen Grad portabel.

Bei einer Bildergalerie, die ich momentan entwickel gibt es z.B. ein "Image"-Model, welches von DbTable erbt. Bilder können veröffentlicht sein oder nicht, also hat das Model zwei Methoden "publish" und "unpublish" erhalten, welche ganz einfach so aussehen:
PHP-Code:

public function publish($id) {
    
$this->updateByCondition(
        array(
            
$this->primary => $id
            
'published'    => 0
        
), 
        array(
            
'published' => 1
            
'modified'  => date('Y-m-d H:i:s')
        )
    );


Das erste Array gibt die Bedingung an, das zweite die Felder und Werte, die aktualisiert werden sollen.
So reduziert sich ein reines veröffentlichen von Bildern im Controller auf:
PHP-Code:

$imageModel->publish($request->getParameter('id')); 

Der Parameter 'id' kann hier eine einzelne Id oder ein Array von Ids sein.
Andernfalls müsste man im Controller stets die korrekte Bedingung mit angeben und dafür sorgen, dass das Feld 'modified' ebenfalls aktualisiert wird.

Aber hier stellt sich eine grundsätzliche Frage, welcher jeder für sich beantworten muss: Fat-Models oder Fat-Controller? ;)
Ich tendiere zu Fat-Models.

Zitat:

Zitat von David (Beitrag 483570)
Ist auf jedenfall schöner als wenn man jeden einzelen Query selbst zusammenschraubt.

So sehe ich das auch, wobei man aber natürlich auch mit Perpared-Statements arbeiten kann.
Als ich mit meiner DbQuery-Klasse angefangen habe gab es dies in der heutigen Form in PHP aber noch nicht bzw. nur als Extra-Modul und mittlerweile habe ich mich an meine Klasse gewöhnt. ;)

David 21.12.2010 17:04

Zitat:

Zitat von mantiz (Beitrag 483566)
Beispiel:
PHP-Code:

$list $dbConnection->select()
        ->
from('table1 t1')
        ->
join('table2 t2''t2.id .''t1.id''left')
        ->
getList(); 

Zur Info:
DbConnection::select() liefert eine vorkonfigurierte Instanz meiner DbQuery-Klasse zurück.
Der Punkt bei "t2.id ." gibt an, dass es sich bei dem Wert "t1.id" um eine Tabellen-Spalte handelt, das ist für das Escapen wichtig.
Bei Mysql wird dadurch aus "t1.id" "`t1`.`id`", ansonsten würde es als String behandelt werden.

In wie fern ist das für das Escapen wichtig? Escapest Du jedes der Attribute, die Du den Methoden mitgibst, bevor du es in die Query einsetzt?

mantiz 21.12.2010 17:23

Jap, mache ich. ;)

Oben genanntes Query würde also zu:
Code:

SELECT * FROM `table1` AS `t1` LEFT JOIN `table2` AS `t2` ON `t2`.`id` = `t1`.`id`
Das war mir deshalb wichtig, da ich (besonders früher, heute nicht mehr so häufig) teilweise Spaltennamen verwende die Schlüsselwörter sind, z.B. "key" oder auch mal "table", die können dann nur gequotet verwendet werden, ansonsten gibt's 'nen Fehler und da ich mir darüber keine Gedanken machen möchte ist das dabei herausgekommen.

inta 21.12.2010 17:38

Warum schreibst du das eigentlich selbst? Erfüllen ORM wie RedBean, Doctrine oder Outlet deine Anforderungen nicht?

Zum Lernen habe ich sowas auch vor einiger Zeit mal geschrieben, aber im produktiven Einsatz würde ich kein eigenes ORM pflegen wollen.

mantiz 21.12.2010 18:22

Zitat:

Zitat von inta (Beitrag 483612)
Warum schreibst du das eigentlich selbst?

Das frage ich mich auch des öfteren. :)

Zitat:

Zitat von inta (Beitrag 483612)
Erfüllen ORM wie RedBean, Doctrine oder Outlet deine Anforderungen nicht?

Wahrscheinlich würden die meine Anforderungen größtenteils erfüllen und bei vielen Dingen weitaus mehr unterstützen.
Von den genannten hatte ich mir allerdings nur Doctrine mal genauer angesehen.

Zitat:

Zitat von inta (Beitrag 483612)
Zum Lernen habe ich sowas auch vor einiger Zeit mal geschrieben, aber im produktiven Einsatz würde ich kein eigenes ORM pflegen wollen.

Stimmt schon, es ist mit einem gewissen Aufwand verbunden.
Ich versuche möglichst viel selbst zu schreiben, weil ich dann nicht (oder nicht so häufig) überrascht werden kann.
Wahrscheinlich könnte ich mir viel Zeit sparen, wenn ich mich einfach mal in ein paar Frameworks einarbeiten würde, aber meistens finde ich irgendwelche Dinge, die mir nicht gefallen und dann muss ich entweder damit arbeiten und ärgere mich ständig darüber oder ich muss einen Workaround finden. ;)

Bitte nicht falsch verstehen, ich finde die Frameworks fast alle super, es ist nur nicht so ganz meins, ich fühle mich bei Eigenentwicklungen einfach wohler.
Ist aber nicht bei jedem so und das ist auch gut so.

laborix 21.12.2010 20:21

Zitat:

Zitat von mantiz (Beitrag 483627)
... aber meistens finde ich irgendwelche Dinge, die mir nicht gefallen und dann muss ich entweder damit arbeiten und ärgere mich ständig darüber oder ich muss einen Workaround finden. ;)

... ich fühle mich bei Eigenentwicklungen einfach wohler. ...

Einer der Gründe, warum ich versuche mit OOP ein eigenes CMS für mich zu entwickeln.

[OT]
Der wichtigste Grund ist bei mir die SQL Datenbank, irgendwie mag ich die Dinger nicht.

Beispiel:
Flatfile bietet die Möglichkeit, Daten zwischen Web, Net-/Notebook und USB-Stick per copy&paste portabel zu machen. Mit SQL geht das nur per aufwändigen Export/Import und ich kann nicht die Betriebssystem Suche zum Durchsuchen von Dateiinhalten verwenden.
[/OT]

Egal, lernen ist angesagt und dieser Thread zeigt wirklich gute Denkanstöße :)

inta 21.12.2010 20:47

Zitat:

Zitat von laborix (Beitrag 483639)
Flatfile bietet die Möglichkeit, Daten zwischen Web, Net-/Notebook und USB-Stick per copy&paste portabel zu machen. Mit SQL geht das nur per aufwändigen Export/Import und ich kann nicht die Betriebssystem Suche zum Durchsuchen von Dateiinhalten verwenden.

Die Portabilität hast du auch mit SQLite, nur die Durchsuchbarkeit wohl (noch) nicht.

paracelsus 21.12.2010 20:49

OT
Leute, ich werde alt. Ich habe nicht den geringsten Tau, was ihr da redet. Ich mag php - sogar recht gerne - aber redet ihr eine andere Sprache hier? - im Vergleich mit euch fühle ich mich wie ein 386er Intel ...
Bin schon wieder wech ...
/OT

David 21.12.2010 22:03

Meinst Du den Objekt-orientierten talk? Davon versteh ich auch nicht wirklich viel. Das ganze ist interessant, klar. Aber die abstrakten Denkweisen muss man erstmal verstehen lernen. Das schaff ich seit zwei Jahren nicht. (Hab aber auch nicht wirklich dran gehangen).

Praktikant 21.12.2010 23:07

Zitat:

Zitat von mantiz (Beitrag 483580)
Am Framework an sich habe ich die letzten 2 Monate gearbeitet, allerdings nicht am Stück. Vorher hatte ich bereits einen Versuch mit nahezu identischen Klassen wie aus dem Buch "PHP Design Patterns" unternommen, habe dann aber festgestellt, dass man Patterns nicht "einfach so" umsetzen sollte.

Das ist ja fast ne halbe Ewigkeit :p Mal schauen wie ich Zeit finde so etwas umzusetzen :)
Zitat:

Zitat von mantiz (Beitrag 483580)
Das stimmt auf jeden Fall, Performance geht verloren, aber das ist klar, anders geht's halt nicht. :)
Für mich besteht der Vorteil darin, dass ich mich nicht um so Dinge wie das quoten der Spalten oder escapen der Werte kümmern muss, weil das von DbQuery automatisch vorgenommen wird, das hilft schonmal bei der Übersichtlichkeit.
Zusätzlich bleibt man zu einem gewissen Grad portabel.

Mir geht es dabei darum eine Klasse/ein Framework zu haben, was ich mit möglichst wenig Änderungen in vielen Projekten schnell einsetzen kann. Damit diese dann schneller vom Stapel laufen. Entwicklungen von anderen mag ich auch nicht so extrem.... Ich habe da immer dieses Gefühl "Hoffentlich geht nichts kaputt, was du noch nicht gefunden hast!" :D

Wie realisierst du das Lazy-Loading? Mit der Methode __autoload() von php, oder hast du dir da auch etwas eigenes geschrieben?

mantiz 22.12.2010 03:28

Zitat:

Zitat von Praktikant (Beitrag 483672)
Wie realisierst du das Lazy-Loading? Mit der Methode __autoload() von php, oder hast du dir da auch etwas eigenes geschrieben?

Ja, per __autoload werden die Dateien automatisch eingebunden und fast jedes Objekt wird erst in den get-Methoden, also bei Bedarf, erstellt.

Ein einfaches Beispiel (ohne zusätzliche Config) könnte sein:
PHP-Code:

public function getRouter() {
   if (!
is_object($this->router) && $this->router !== null) {
      
$routerClass = (string)$this->router;
      
$this->router = new $routerClass();
      return 
$this->router;
   }
   return 
null;


Im Setter kann entweder ein Objekt oder ein String (Klassenname) übergeben werden.
So sind sämtliche Klassen schonmal änderbar, ohne dass man die Objekte im Vorfeld erstellen muss, nur bei zusätzlicher Config.

David 22.12.2010 11:27

Was genau macht denn deine Routerklasse?

mantiz 22.12.2010 12:24

Der Router ermittelt den Controller und die Action, welche aufgerufen werden soll anhand eines Strings.
Ich verwende dazu im Frontcontroller die RequestUri, aber man könnte auch einen GET-Parameter verwenden oder sonstwas.

Routen können dann z.B. so aussehen:
Code:

<auth>
        <route>/:action/*</route>
        <defaults>
                <controller>auth</controller>
                <action>login</action>
        </defaults>
        <regex>
                <action>login|logout</action>
        </regex>
</auth>

Im Grunde ist das ähnlich dem Regex-Router von Zend. Und CakePHP macht es, wenn ich mich recht erinnere, auch so ähnlich.
Die Route wird in einen regulären Ausdruck übersetzt und geprüft, ob dieser Ausdruck auf den String passt, dann werden anhand dessen die Variablen (hier nur action) und Übergabe-Parameter (alles was auf * passt) bestimmt und ggfs. die Defaults gesetzt.
Anschließend werden noch die Variablen gegen die Ausdrücke in "regex" geprüft, wenn alles stimmt, wird die Route verwendet.
Hier wird die Action auf "login" und "logout" beschränkt, die Route passt also nur für Anfragen der Form "/login", "/login/*", "/logout", "/logout/*".
Der angegebene Controller-Name ist ein eindeutiger Schlüssel für den Controller.

Die Config vom Controller sieht dann so aus:
Code:

<controllers>
        <auth>
                <class>Auth_Controller</class>
                <loginRedirectUrl>/admin</loginRedirectUrl>
        </auth>
</controllers>

Der Auth-Controller stellt bei mir das Login-Formular dar und führt bei einem Post-Request einen Login durch.
Man kann aber auch einen anderen Auth-Controller schreiben und diesen so ziemlich simpel in der Config ändern.

Die ganze Config scheint aufwendig zu sein, aber bei manchen Frameworks ist das so, dass diese einfach ein festes URI-Schema verwenden, was dann so ähnlich aussieht wie: /<controller>/<action>/<params>.
Wobei der default von <controller> und <action> meistens auf "index" gesetzt wird und die Parameter natürlich optional sind.
Das bedeutet aber, dass die URIs quasi fest vorgegeben sind, die Controller müssen also entsprechend den gewünschten URIs benannt werden.
Und genau dafür ist der Router da.

David 22.12.2010 12:55

Also zusammengefasst parst der Router die Permalinks und entscheidet, wie es weiter geht?!

mantiz 22.12.2010 13:38

So ungefähr, ja.


Alle Zeitangaben in WEZ +2. Es ist jetzt 07:52 Uhr.

Powered by vBulletin® Version 3.8.11 (Deutsch)
Copyright ©2000 - 2021, vBulletin Solutions, Inc.

© Dirk H. 2003 - 2020