Zugriff auf Eigenschaften einer fremden Klasse
Andreas Korthaus
- php
Hallo!
Habe da ein Problem mit der OOP.
Ich habe Variablen, also Eigenschaften in einer Klasse, die ich mit einem Wert belegt habe. Jetzt möchte ich von einer anderen KLasse direkt auf diese Werte zugreifen, aber das funkitoniert nicht. Wieso das?
Also bsp:
class Config {
var $lang = array();
function Config() {
$this->lang[] = "de";
$this->lang[] = "en";
}
}
$config = new Config;
class Request {
var $used_language;
var $scriptname;
function Request() {
$lang = implode("|", $config->lang)
preg_match("/^/((".$lang.")/)?(.*)$/",$_GET["url"],$url_match);
$this->used_language = $url_match[2];
$this->scriptname = $url_match[3];
}
}
Innerhalb der Klasse "Request" stzeht in $config->lang "NULL". Muß ich mir jetzt für jede Variable/Eigenschaft die ich extren(in einer anderen Klasse) verwenden will eine extra Methode schreiben?
Viele Grüße
Andreas
hio Andreas,
$config = new Config;
class Request {
var $used_language;
var $scriptname;
function Request() {
$lang = implode("|", $config->lang)
preg_match("/^/((".$lang.")/)?(.*)$/",$_GET["url"],$url_match);
$this->used_language = $url_match[2];
$this->scriptname = $url_match[3];
}
}Innerhalb der Klasse "Request" stzeht in $config->lang "NULL". Muß ich mir jetzt für jede Variable/Eigenschaft die ich extren(in einer anderen Klasse) verwenden will eine extra Methode schreiben?
Nein, $config ist in dem aktuellen Scope (also innerhalb deiner Instanz) einfach nicht bekannt. Du hast diese auf dem globalen Scope definiert und kannst über den darauf zugreifen. also
$lang = implode("|", $GLOBALS["config"]->lang) oder über global $config in den Scope "importieren"
Vom Gefühl her, hätte ich das etwas anders gelöst, wobei ich ehrlich nicht sagen kann ob das dann auch besser ist. Ich hätte aus Request heraus eine Instanz von config erzeugt. Ich denke liegt daran, das ich ungerne mit "globalen" arbeite. Oder ein anderer Vorschlag wäre,
du könntest auch die Klasse config auch umschreiben
class Config {
var $lang = array();
function Config() {
$this->lang[] = "de";
$this->lang[] = "en";
return $this->lang;
}
}
So liefert der Constructor das Array lang zurück, beim Instanzieren stört das nicht weiter, d.h. er liefert die Instanz (oder genauer die Referenz auf eine Kopie der Instanz) wobei du nun auch die Funktion Config ohne Instanz aufrufen kannst und dabei das Array lang bekommst. Also,
function Request() {
$lang = implode("|", config::config();)
preg_match("/^/((".$lang.")/)?(.*)$/",$_GET["url"],$url_match);
$this->used_language = $url_match[2];
$this->scriptname = $url_match[3];
}
aber wie gesagt, muss nicht besser sein, wollte nur eine andere Idee reinbringen. Bin nicht ganz wach, also sry wegen evtl. "Sprachungenauheiten" ;)
gl & hf
Thorsten
Hallo Thorsten,
ich habe noch nie in PHP (doch, vor ein paar Tagen das erste
Mal ;-)) objektorientiert programmiert, deshalb hab ich zwei
Fragen:
function Request() {
$lang = implode("|", config::config();)
preg_match("/^/((".$lang.")/)?(.*)$/",$_GET["url"],$url_match);
$this->used_language = $url_match[2];
$this->scriptname = $url_match[3];
}
Wenn ich das richtig verstanden habe, darf nur ein Variablen-
zeichen stehen, also nur $this->used_language, es sei denn ich
möchte den Wert von $used_language als Variablennamen verwenden,
dann ist $this->$used_language richtig - stimmt's?
Wo liegt der Unterschied zwischen $bar und $foo->bar?
Bye,
Peter
Hallo!
- Wenn ich das richtig verstanden habe, darf nur ein Variablen-
zeichen stehen, also nur $this->used_language, es sei denn ich
möchte den Wert von $used_language als Variablennamen verwenden,
dann ist $this->$used_language richtig - stimmt's?
Denke schon, habs noch nie probiert, zumindest funktioniert das bei normalen Variablen mit $$name
- Wo liegt der Unterschied zwischen $bar und $foo->bar?
$bar ist der eigentliche Name der Variable, wenn Du eine Variable als Eigenschaftz der Klasse verwenden willst dann mußt Du innerhalb der Klasse mit $this->bar drauf zugreifen, außerhalb mit dem Namen der Instanz der Klasse, wenn Du also
$foo = new meine_tolle_klasse;
gemacht hast, kannst Du mit
$foo->bar auf die Eigenschaft $bar in der Instanz $foo der Klasse "meine_tolle_klasse" zugreifen.
Ne kleine Einführung findest Du hier:
Grüße
Andreas
Hallo Thorsten,
ich habe noch nie in PHP (doch, vor ein paar Tagen das erste
Mal ;-)) objektorientiert programmiert, deshalb hab ich zwei
Fragen:function Request() {
$lang = implode("|", config::config();)
preg_match("/^/((".$lang.")/)?(.*)$/",$_GET["url"],$url_match);
$this->used_language = $url_match[2];
$this->scriptname = $url_match[3];
}
- Wenn ich das richtig verstanden habe, darf nur ein Variablen-
zeichen stehen, also nur $this->used_language, es sei denn ich
möchte den Wert von $used_language als Variablennamen verwenden,
dann ist $this->$used_language richtig - stimmt's?
Mal sehen ob ich das in Worte fassen kann ... ;)
$this->used_language bezieht sich auf die Variable der Instanz selbst. Sie ist eine "Objektvariable". D.h. z.b.
class Test() {
$used_language = "de";
}
Innerhalb der Instanz selbst sprichst du nun diese per this->used_language an. Von ausserhalb benutzt du die Referenz auf diese Instanz als z.b.
$Test = new Test;
print $Test->used_language;
Während bei $this->$used_language, $used_language selbst eine Variable ist unabhängig von der Instanz. D.h. was immer in $used_language steht wird als Eigenschaftsname genommen.
z.b.
$parameter = "used_language";
$this->$parameter // steht nun für $this->used_language
hm, hoffe war verständlich genug ;)
Es gibt deren Dinge, die man zwar versteht aber schlecht erklären kann ... ;)
gl & hf
Thorsten
Hallo!
@Peter: besser nicht weiterlesen denn das ist erstmal irrelevant und verwirrt vermutlich nur!
Von ausserhalb benutzt du die Referenz auf diese Instanz als z.b.
$Test = new Test;
print $Test->used_language;
Referenz wäre doch
$bar =& new fooclass();
das hieße es wird eien Referenz auf die eigebtliche Klasse erstellt, und keine Kopie erzeugt(http://php3.de/manual/de/language.references.whatdo.php).
Das hört sich ja eigentlich vernünftig an, vor allem wegen Performance, jetzt ist nur die Frage wie mich das dann einschränkt. Mit Referenzen kann ich nur eine Instanz der Klasse verwenden, denn wenn ich mehrere Referenzen wie oben auf ein und dasselbe Objekt habe dann kommen die sich doch vermutlich ins Gehege, oder?
Genaus mit :: , funktioniert das noch genau so denn die ursprüngliche Klasse wird ja jetzt verwendet, an Stelle einer Kopie!
Liege ich in meinen Befürchtungen richtig oder nicht?
Grüße
Andreas
hio,
$Test = new Test;
print $Test->used_language;
Referenz wäre doch
$bar =& new fooclass();
das hieße es wird eien Referenz auf die eigebtliche Klasse erstellt, und keine Kopie
Nicht ganz (oder?), mit $bar = new fooclass(); erzeugst du eine Instanz und eine Kopie dieser Instanz un erhählst die Referenz auf diese Kopie (call by value), auf die eigentliche Instanz kannst du nun nicht mehr zugreifen.
Mit $bar = & new fooclass(); erzeugst du eine Instanz und bekommst eine Referenz auf diese Instanz.
Also eine Referenz bekommst du allemale, der Unterschied liegt im kopieren der Instanz. Oft spielt es keine Rolle ob du nun mit der Instanz oder der Kopie arbeitest, wenn du nun aber von verschiedenen Punkten aus auf Werte der Instanz zugreifen willst, dann es eine Refrenz auf die Instanz selbst der Weg.
gl & hf
Thorsten
Hi!
Nein, $config ist in dem aktuellen Scope (also innerhalb deiner Instanz) einfach nicht bekannt. Du hast diese auf dem globalen Scope definiert und kannst über den darauf zugreifen.
War eigentlich klar. Also brauche ich jetzt für jede Variable auf die ich zugreifen möchte eine extra Methode um drauf zuzugeifen, Deine Lösung ist nicht so gut für mich da ich ca. 20 Werte in 10 Variablen habe(teilweise Arrays). Also brauche ich wenigstens 10 Methoden die immer den enstprechenden Wert zurückgeben. Mit global möchte ich nicht arbeiten, da mir das eigenltich zu weit in die fremde Klasse geht.
Also gibt es keine "schönere" Schnittstelle zwischen den beiden Modulen/Klassen, also diese 10 Methoden, oder?
Grüße
Andreas
Hio,
Also gibt es keine "schönere" Schnittstelle zwischen den beiden Modulen/Klassen, also diese 10 Methoden, oder?
Spontan fällt mir wenig ein, du könntest mit einer einzigen Methode arbeiten, der du mitteilst welchen Wert du haben möchtest und sie in dir liefert.
class Config {
var $lang = array();
function Config() {
$this->lang[] = "de";
$this->lang[] = "en";
}
function getValue($valueName) {
return $this->$valueName;
}
}
gl & hf
Thorsten
Hallo Thorsten,
Spontan fällt mir wenig ein, du könntest mit einer einzigen Methode arbeiten, der du mitteilst welchen Wert du haben möchtest und sie in dir liefert.
class Config {
var $lang = array();
function Config() {
$this->lang[] = "de";
$this->lang[] = "en";
}function getValue($valueName) {
return $this->$valueName;
}
}
Was kläglich versagen wird, denn wenn getValue als statische Methode aufgerufen wird (Config::getValue (...)) dann gibt es in der Methode kein $this und das Script wird von PHP unsanft beendet. Am besten, Du instantiierst ganz am Anfanng ein Objekt der Klasse Config und speicherst es mit einem Namen, den Du sicherlich nicht im Script wiederverwendest.
----------------------------------------------
class Config {
var $lang = array();
function Config() {
$this->lang[] = "de";
$this->lang[] = "en";
}
function getValue($valueName) {
global $__gv_config; // gv steht für »global variable«
if (!is_object ($__gv_config)) { // zur Sicherheit, kannst Du auch,
$__gv_config = new Config(); // wenn Du mutig bist, weglassen
}
return $__gv_config->$valueName;
}
}
$__gv_config = new Config();
----------------------------------------------
Grüße,
Christian
Hallo christian!
class Config {
var $lang = array();
function Config() {
$this->lang[] = "de";
$this->lang[] = "en";
}function getValue($valueName) {
global $__gv_config; // gv steht für »global variable«
if (!is_object ($__gv_config)) { // zur Sicherheit, kannst Du auch,
$__gv_config = new Config(); // wenn Du mutig bist, weglassen
}
return $__gv_config->$valueName;
}
}$__gv_config = new Config();
Was meinst Du denn allgemein dazu? Wie programmiert man am beste solche Schnittstellen? Globale Variablen scheinen mir der falsche Weg zu sein, oder?
Also mit der Methode die mir auf Anfrage eine bestimmte Variable aus der Klasse übergibt würde ich das jetzt machen.
Oder würdest Du so eine Schnittstelle anders programmieren?
Viele Grüße
Andreas
Hallo Andreas,
Was meinst Du denn allgemein dazu?
Hmm. Vielleicht für so Konfigurationsinformationen keine Klasse sondern ein assoziatives Array nehmen...?
Wie programmiert man am beste solche Schnittstellen? Globale Variablen scheinen mir der falsche Weg zu sein, oder?
Naja, Du könntest auch folgendes machen (im Nachinein eleganter):
class A {
var $hallo = 'test';
function A () {
// nichts tun
}
function B () {
// teste, ob die Klasse instantiert ist...
if (!isset ($this)) {
$this = new A;
}
// nun normal $this verwenden
}
}
$a = new A;
// folgende Zeilen haben den gleichen Effekt
$a->B();
A::B();
Getestet: PHP 4.3.0
Also mit der Methode die mir auf Anfrage eine bestimmte Variable aus der Klasse übergibt würde ich das jetzt machen.
Das wäre, zumindest mit der »neueren« Lösung durchaus denkbar.
Oder würdest Du so eine Schnittstelle anders programmieren?
Gegenfrage: Was willst Du denn genau mit Deiner Schnittstelle erreichen?
Grüße,
Christian
Hallo!
Naja, Du könntest auch folgendes machen (im Nachinein eleganter):
Jetzt verwirr mich nicht mit solchen Sachen ;-)
Oder würdest Du so eine Schnittstelle anders programmieren?
Gegenfrage: Was willst Du denn genau mit Deiner Schnittstelle erreichen?
Nochmal meine Config-Klasse, etwas erweitert:
class Config {
var $db = array();
var $lang = array();
var $usergroup = array();
var $modules = array();
var $smarty = array();
// globale Pfad-Angaben
var $root_path = '/www/test/';
// sonstige Einstellungen
var $output_compress = true;
function Config () {
// Datenbank-Angaben
$this->db['typ'] = 'mysql';
$this->db['name'] = 'name';
$this->db['host'] = 'localhost';
// verfügbare Sprachen
$this->lang[] = 'de';
$this->lang[] = 'en';
// verfügbare Usergruppen
$this->groups[] = 'admin';
$this->groups[] = 'intern';
$this->groups[] = 'lieferanten';
// verfügbare Module(Plugins)
$this->modules[] = 'basic';
$this->modules[] = 'Fragebogengenerator';
// SMARTY Einstellungen
$this->smarty['compile_check'] = true
}
}
$config = new Config;
Die Idee dahinter war einfach, dass ich die Konfig-Daten so in einer Klasse habe und so später noch die Speicherung... der Daten ändern kann, ohne dass sich di3 Schnittstelle ändern muß. Das Hauptargument war aber das ich dachte ich könne aus anderen klassen direkt auf Eigeschaften in Config zugreifen, aber das ist ja definitiv falsch, daher sollte ich mir das durchaus nochmal überlegen. Nur wenn ich die Config-Daten in einem Array habe, dann wird es ja noch schwieriger drauf zuzugreifen, denn dann komme ich auch um global nicht mehr drum herum.
Diese Schnittstelle zu anderen Klassen brauche ich ja an vielen Stellen, so z.B. bei einem HTTP-Request, ich habe die URLs jetzt so aufgebaut:
http://www.server.de/{sprache}/{user-Typ}/{Modul-Name}/{Scriptname}
Das nehme ich dann innerhalb der folgenden Klasse auseinander, um für das Script die entsprechenden Daten in Variablen zu überführen.
So weiß ich welches Sprachmodul ich zu laden habe, um was für einen User es sich handelt, ich habe für die Usergruppen eigene Scripte weil sie komplett andere Seiten haben, also alles für Lieferanten heißt dann z.B. lieferanten.{scriptname}.php. Den Modul-Namen brauche ich ebenfallls immer, da ich für die Module (oder Plugins wie Christian Kruse sie vermutlich richtiger genannt hat) ja jeweils eigene Verzeichnisse habe. Ich habe halt ein Basismudul und eben zuschaltbare Erweiterungen wie der "FragebogenGenerator", der bekommt dann im Verzeichnis "module" ein eines Unterverzeichnis "FragebogenGenerator", neben "basismodul" und den übrigen Modulen.
in index.php habe ich dann mit
ROOTPATH/module/{Modul-Name}/{user-Typ}.{Scriptname}.php
Das Script welches per include eingebunden wird.
(ich hoffe das ist zu verstehen ;-), zum besseren Verständnis siehe: [1])
So sieht dann z.B. meien Request-Klasse aus, die den obigen HTTP-Request in Variablen übersetzt(stark gekürzt!):
class Request {
var $used_language;
var $scriptname;
function Request() {
$lang = implode("|", global $config->lang)
preg_match("/^/((".$lang.")/)?(.*)$/",$_GET["url"],$url_match);
$this->used_language = $url_match[2];
$this->scriptname = $url_match[3];
}
}
Ich verwende die Daten aus der Config-Klasse um alle verfügbaren Auswahlmöglichkeiten zu bekommen, hier am Beispiel Language, mit "de|en".
So kann ich sicherstellen das nur das passiert was ich will, bzw. was in config als verfügbar eingestellt ist.
Dasselbe mache ich auch in der Smarty Klasse, da habe ich auch enige Einstellungen die aus Config übernommen werden sollen. Und auch das DB-Modul holt sich so seine Zugangsdaten.
Ich überlege die ganze Zeit, aber die Struktur ist wirklich kompliziert, ich kann es Dir ja mal "aufmalen":
[1]
http://www.knet-systems.de/temp/struktur.gif
Im Verzeichnis "config/" liegt obige Klasse "Config"
HTTP-ROOT ist wie der Name schon sagt das Verzeichnis "http-root/"
Darin liegt eine .htaccess die alle Requests auf die ebenfalls dort liegende index.php leitet, Du erinnerst Dich sicher.
die "http-root/index.php" schlüsselt den Request auf und läd entsprechnde Scripte(include)
Alles was nach außen Sichtbar ist liegt im Verzeichnis "modules/", normalerweise im "modules/basic/", und die Erweiterungen halt in den enstsprechneden Verzeichnissen. Alle Modul-Verzeichnisse enthalten einen ordner für eigene Scripte die nur dort eingebunden werden:
"modules/{modulname}/inludes" udn entsprechnd für Tenplates udn Language-Files.
Und die eigentlichen Scripte die Aufgerufen werdne haben imj namen noch stehen, für wen soe vorgehen sind, loeferaht.script.php, admin.script.php...
So das wäre alles ich hoffe Du kannst Das ein wenig nachvollziehen, bzw. entschuldige ich mich für den langen Text und bedanke mich nochmal für die viele Hilfe von Dir in letzter Zeit!
Viele Grüße
Andreas
Hallo Andreas,
Dann wollen wir mal...
// SMARTY Einstellungen
$this->smarty['compile_check'] = true
}
function getCfgVar ($var) {
if (!isset ($this)) { $this => new Config; }
return $this->$var;
}
}
$config = new Config;
Diese Zeile brauchst Du nicht mehr.
aber das ist ja definitiv falsch, daher sollte ich mir das durchaus nochmal überlegen.
Jetzt nicht mehr »falsch« sondern nur etwas umständlich:
$a = Config::getCfgVar('smarty');
var_dump ($a['compile_check']);
So sieht dann z.B. meien Request-Klasse aus, die den obigen HTTP-Request in Variablen übersetzt(stark gekürzt!):
preg_match("/^/((".$lang.")/)?(.*)$/",$_GET["url"],$url_match);
Wieso prüfst Du nicht das Ergebnis von preg_match?
Übrigens: Wenn Du die URL mit explode nach '/' auftrennst, dann ist die Funktion array_shift geradezu genial zu verwenden. So mache ich es zumindest. Wenn Du eine feste Struktur hast, dann reicht einfach der Direktzugriff auf das Array:
$path = explode ('/', $_GET['url']);
$lang = $path[0];
$usertype = $path[1];
$module = $path[2];
$script = $path[3];
if (!in_array ($lang, Config::getCfgVar ('lang'))) {
// oops - fehler
}
// weitere Validierung
So das wäre alles ich hoffe Du kannst Das ein wenig nachvollziehen, bzw.
Ja, das Konzept an sich finde ich gar nicht schlecht, wenn Du das noch richtig ausarbeitest, dann könnte das wirklich was werden. :-)
entschuldige ich mich für den langen Text
macht nix, ich habe ihn aufs nötigste reduziert. :-)
und bedanke mich nochmal für die viele Hilfe von Dir in letzter Zeit!
Ach weißt Du, ich befasse mich im Moment mit ähnlichen Problemen, _sehr_ ähnlichen Problemen, und von daher ist das ganze nicht ganz uneigennützig. :-)
Grüße,
Christian
Hallo Christian!
Dann wollen wir mal...
das hört sich gut an ;-)
// SMARTY Einstellungen
$this->smarty['compile_check'] = true
}
function getCfgVar ($var) {
if (!isset ($this)) { $this => new Config; }
prüfst Du so ob es eine Instanz der Klasse gibt oder was machst Du da? Wenn Du mit :: zugreifst _brauchst_ Du doch überhaupt keine Klasse! Und wennich doch eine Instanz brauche dann doch liebr eien Referenz auf die Klasse, oder?
return $this->$var;
}}
Jetzt nicht mehr »falsch« sondern nur etwas umständlich:
$a = Config::getCfgVar('smarty');
var_dump ($a['compile_check']);
Ist das was Du jetzt gemachst hast umständlich oder optimal? Welche Version meinst Du oben?
So sieht dann z.B. meien Request-Klasse aus, die den obigen HTTP-Request in Variablen übersetzt(stark gekürzt!):
preg_match("/^/((".$lang.")/)?(.*)$/",$_GET["url"],$url_match);
Wieso prüfst Du nicht das Ergebnis von preg_match?
Wiel ich einfach die ursprüngliche RegEx /^/(de|en).../ weiterbearbeitet habe, ist wohl Quatsch, wobei - ich kann nicht immer garantieren das die URL-Struktur so wie oben beschreiben aussieht. Daher have ich alle Ausdrücke mit ()? versehen so bekomme ich auch wenn z.B. /de/ fehlt immer noch die richtigen Werte in die Variablen. So schalte ich eine potentielle Fehlerquelle ab.
Übrigens: Wenn Du die URL mit explode nach '/' auftrennst, dann ist die Funktion array_shift geradezu genial zu verwenden. So mache ich es zumindest. Wenn Du eine feste Struktur hast, dann reicht einfach der Direktzugriff auf das Array:
$path = explode ('/', $_GET['url']);
$lang = $path[0];
$usertype = $path[1];
$module = $path[2];
$script = $path[3];
Wie gesagt, ich bin noch nicht sicher ob die URL immer 100% so sein kann, ich befürchte nicht, in einem Bereich z.B. reicht der Parameter Sprache, da dieser eh frei zugänglich ist.
So das wäre alles ich hoffe Du kannst Das ein wenig nachvollziehen, bzw.
Das hatte ich grade aus Versehen faslch gemacht:
<img src="http://www.knet-systems.de/temp/struktur.gif" border="0" alt="">
Ja, das Konzept an sich finde ich gar nicht schlecht, wenn Du das noch richtig ausarbeitest, dann könnte das wirklich was werden. :-)
Was würde Dich am meisten stören? Mien großes Problem ist die Komplexität:
1. habe 4 verschidene Benutzegruppen die jeweils einen eigenen Login-Bereich haben müssen, mit verschiedenen Funktionalitäten...
2. Müssen Module unabhängig von der Basisvwersion hinzufügbar und entfernbar sein. Die Module können auf alle 4 Benutzergruppen-eigene Seiten Einfluß haben, ob jetzt Menüstruktur, extra Seiten/-Funktionalitäten, Datenbank-Tabellen...
Das sind eigentlich schon die Hauptprobleme. ich habe das jetzt so gemacht, das ich das Verzeichnis "module/fragenbogengenerator/" hinzufüge und somit auf dieses Modul zugreifen kann, und wenn ich es entferne verschinden die Funktionalitäten und Menüpunkte wieder. Sicher sinddas noch ein paar Kleinigkeiten die ich noch nicht im Detail geplant habe, aber ich denke das müßte ich so hinbekommen. Vermutlich mache ich ein "add.module.fragebogengenerator.php" -Script, welches alle Einstelluneg vornimmt, und genauso "delete.module.fragebogengenerator.php" welches alles wieder entfernt.
So ganz 100% ist das zwar noch nicht, aber es wird langsam. Wirklich weit bin ich aber noch nicht, außer der Verzeichnisstruktur und den ersten paar Basis-Scripten steht da noch nicht viel, aber das einbinden des "requested" Scripts funktioniert, dessen Ausgabe mit Smarty funktioniert auch, zugriff auf die Datenbank via PEAR auch, Und das Konfigurieren klappt auch so langsam, das Parsen des Request und der GET/POST Parameter auch... jetzt muß ich das Basismudul, welches als reines Scripte-Version schon steht in diese Struktur einbinden, dort Smarty und PEAR::DB einbinden... wenn das mal läuft bin ich schonmal froph, aber so langsam sehe ich wenigstens mal einen kleinen Erfolg, wenn sich alles nur in meinem Kopf abspielt ist das auf die Dauer wirklich demotovierend ;-)
Wenn Dir was an meinem Konzept, oder der Verzeichnisstruktur oder woran auch immer nicht passt sag es bitte, egal was, ich bin nämlich noch sehr unsicher da es noch nicht ganz optimal ist, weil ich auch noch keine Erfahrung mit sowas habe, weder mit OOP, noch mit modularem Programmieren überhaupt, noch mit SMARTY und auch nicht mit PEAR, also beste Voraussetzungen ne ganze Menge zu lernen ;-)
Viele Grüße
Andreas
Hallo Andreas,
prüfst Du so ob es eine Instanz der Klasse gibt oder was machst Du da?
Ich prüfe, ob die Methode statisch aufgerufen wurde (Klasenname::Methode) oder von einem Objekt aus. (Objekt->Methode) Wenn ersteres der Fall ist, dann gibt es kein Objekt und auch keine Variablen. Daher muss ich es erzeugen.
Wenn Du mit :: zugreifst _brauchst_ Du doch überhaupt keine Klasse!
Klasse ja, Instanz nein.
Und wennich doch eine Instanz brauche dann doch liebr eien Referenz auf die Klasse, oder?
Wie gesagt, es geht hier einfach darum: Wenn eine Klasse nicht instantiert ist, dann kannst Du nicht auf die Variablen dieser Klasse zugreifen. Du musst sie also instantieren oder eine vorher vorhandene Instanz
Ist das was Du jetzt gemachst hast umständlich oder optimal?
Optimal - nein. Es ist ein Hack. Aber einfacher, denn Du kannst auf die Elemente einer Klasse zugreifen, obwohl die Klasse nicht instantiert wird. Dafür wird die Klasse jedes Mal instantiert. In dem Fall täte eine globale Variable (wie mein allererster Vorschlag in diesem Thread) besser.
Welche Version meinst Du oben?
Hä?
Wiel ich einfach die ursprüngliche RegEx /^/(de|en).../ weiterbearbeitet habe, ist wohl Quatsch, wobei - ich kann nicht immer garantieren das die URL-Struktur so wie oben beschreiben aussieht. Daher have ich alle Ausdrücke mit ()? versehen so bekomme ich auch wenn z.B. /de/ fehlt immer noch die richtigen Werte in die Variablen. So schalte ich eine potentielle Fehlerquelle ab.
Das Fragezeichen hatte ich ganz übersehen... Achso, ja dann ist ja ok.
- habe 4 verschidene Benutzegruppen die jeweils einen eigenen Login-Bereich haben müssen, mit verschiedenen Funktionalitäten...
Löse das über eine Rechteverwaltung. Du kennst "Access Control Lists"? (Beispiel: Rechteverwaltung unter Win NT, 2000, XP und .NET Server) Wenn Du Access Control Lists implementierst, und zwar Rechte auf _jedes_ Objekt, also Menüeinträge, Module, etc. - dann kannst Du das ganze nur mit einem Login lösen und hast das ganze enorm vereinfacht.
- Müssen Module unabhängig von der Basisvwersion hinzufügbar und entfernbar sein. Die Module können auf alle 4 Benutzergruppen-eigene Seiten Einfluß haben, ob jetzt Menüstruktur, extra Seiten/-Funktionalitäten, Datenbank-Tabellen...
Module sollte erst einmal unabhängig vom Menü sein. Du solltest in einer Menüverwaltung die Module manuell mit einem Menüpunkt verknüpfen können. (Genaugenommen speicherst Du dann einen Pfad zum Menüpunkt, der dann verlinkt wird) Du musst natürlich auch aufpassen, dass kein Idiot ein Modul manuell »ausprobiert«. Dazu musst Du abfangcode schreiben.
und wenn ich es entferne verschinden die Funktionalitäten und Menüpunkte wieder. Sicher sinddas noch ein paar Kleinigkeiten die ich noch nicht im Detail geplant habe, aber ich denke das müßte ich so hinbekommen.
Schlechte Idee, siehe einen Absatz höher.
Vermutlich mache ich ein "add.module.fragebogengenerator.php" -Script, welches alle Einstelluneg vornimmt, und genauso "delete.module.fragebogengenerator.php" welches alles wieder entfernt.
Schlechte Idee. Im Prinzip sollte ein Modul (oder Untermodul oder wie Du es organisierst) eine Datei sein. Diese Datei musst Du hochladen. Dann steht das Modul in der Administration zur Verfügung. In der Administration kannst du das Modul dann einrichten. Wenn das Modul Tabellen braucht, dann hast Du noch 2 zusätzliche SQL-Scripte, die Du dann einspielen kannst - eines, um die erforderlichen Tabellen zu erstellen und eines, um sie wieder zu löschen. Diese solltest Du auch manuell einspielen. (evtl. über ein Administrationsinterface, aber immer noch manuell)
Wirklich weit bin ich aber noch nicht, außer der Verzeichnisstruktur und den ersten paar Basis-Scripten steht da noch nicht viel, aber das einbinden des "requested" Scripts funktioniert, dessen Ausgabe mit Smarty funktioniert auch, zugriff auf die Datenbank via PEAR auch, Und das Konfigurieren klappt auch so langsam, das Parsen des Request und der GET/POST Parameter auch...
Das ist doch schon mal etwas.
wenn sich alles nur in meinem Kopf abspielt ist das auf die Dauer wirklich demotovierend ;-)
ACK.
Wenn Dir was an meinem Konzept, oder der Verzeichnisstruktur oder woran auch immer nicht passt sag es bitte,
Siehe oben. ;-)
Grüße,
Christian
Hallo Christian!
- habe 4 verschidene Benutzegruppen die jeweils einen eigenen Login-Bereich haben müssen, mit verschiedenen Funktionalitäten...
Löse das über eine Rechteverwaltung. Du kennst "Access Control Lists"? (Beispiel: Rechteverwaltung unter Win NT, 2000, XP und .NET Server)
Was heißt kenne? Ich habe mich schonmal als User unter Win2K oder Linux eingewählt, sowas in der Art hätte ich auch gerne, nur habe ich zur Zeit das Problem, das sich mindestens 5 wirklich umfassende neue Gebiete alle gleichzeitig in einem Projekt das erste mal ausprobiere, bzw. versuche zu verstehen, das wird mir langsam alles zu kompliziert, ich blicke jetzt schon kaum noch durch, eben weil das so viele unbekannte Techniken sind, noch sowas kann ich zur Zeit glaube ich nicht mehr verkraften denn die Entwicklung wird auch immer langsamer dadurch.
Wenn Du Access Control Lists implementierst, und zwar Rechte auf _jedes_ Objekt, also Menüeinträge, Module, etc. - dann kannst Du das ganze nur mit einem Login lösen und hast das ganze enorm vereinfacht.
Ich mache ja ein Login. ich habe 2 Tabellen:
1. Tabelle: "User" mit den Spalten "UserID","GroupID", "Username", "Password", "Status"(damit kann ich einen User sperren)
2. Tabelle: "Groups" mit den Spalten "GroupID", "GroupName", "Status"(damit kann ich eine Gruppe sperren)
Ich prüfe nach erfolgreichem Login in welcher Gruppe der User ist, also z.B. Group-Name "lieferanten". Damit habeich die Angabe welches Script er verwenden kann. Es ist nicht wie bei Windows wo alle User im Prinzip zu 98% das gleiche Programm haben nur mit ein paar individuell unterschiedlichen Einstellungen und Rechten. Bei mir sind es grundverschiedene Menüs, mit genau gegensätzlichen Funktionen. Daher liegt es für mich nahe das z.B. Lieferanten alles eigene Scripte haben, was die Ausgabe und Interaktion angeht. Genauso eigene Templates und eigene Language-Files. Ich hatte daher erst gedacht, ich lege ein extra Verzeichnis für jeden Group-Name an, aber das wird dann kompliziert mit den Modulen. Wie gesagt sind meine Module eher Plugins, ich nenne sie nur so da ich persönlich den Begriff passender finde.
Ein Beispiel für ein "Modul" wäre wie gesagt der "Fragebogen-Generator". Das ist eine Erweiterung des Basis-Programms, und zwar um je 2 Webseiten bei 3 der 4 Benutzergruppen. Das hieße ich müßte in 3 ordner 6 Scritpe, Lang-Files und Templates verteilen. kann es nicht sein. Und je einen Unterordner pro Modul ist auch nicht viel besser. Alles was das Modul braucht muss in ein Verzeichnis, und so habe ich es auch gemacht. In dem Verzeichnis befinden sich jetzt alle Scripte, Templates und Lang-Files die ich jetzt in dem Beispiel Fragebogen-Generator brauche.
In dem Modul-Ordner liegt dann auch ein Script welches die Funktionen etc. enthält, die das Basis-scrtipt(index.php) braucht um z.B. die Menü-Struktur oder die Rechtevergabe zu regeln, wobei ich mir das bei letzterem nicht ganz vorstellen kann wie das funktionieren soll. Der eingeloggte "lieferant" kann innerhalb der Module nur auf Scripte mit "lieferant.{scriptname}.php" zugreifen. Wenn ich diese Benennung aber abschaffe, dann wird das ganze _sehr_ unübersichtlich, woher weiß ich jetzt hinterher für wen welche Scripte waren, wer auf was genau zugreift...
Womit Du Recht hast ist das ich nicht "lieferant" über die url mitschleppen muß, er muß sich eh jedesmal authentifizieren und so kann ich es auch ermitteln.
Wie würde denn so eiej Rechtevergae jetzt praktisch aussehen? Mein modul.setup.php Script enthält jetzt z.B. eine Klasse in der Methoden stehen aus denen sich das Basisscript Infos zur Navigationsleirste holen soll, genauso könnte da eine Methode für Rechtevergabe stehen.
Nur was genau sollte die machen? Sicher kein Problem, einfach sagen wer Zugriff hat und wer nicht, z.B. in dem die Methode einen Array zurückgibt mit
array("lieferanten => true, "admin" => false...);
Nur was mache ich dann im Basisscript mit der Information? Das wäre lediglich ein zusätzlicher Sicherheitsmechanismus, was ich aber eiugenbtlich schon durch die dynamisch zusammengesezten Namen habe.
Wenn Vom Browser ein HTTP Request kommt bekomme ich folgende Informationen:
Welcher User? => Group-Name
Modulename aus URL
Scriptname aus URL
ggfs. Parameter aus Umgebuingsvariablen
Dann setzt das Bsisscript an und formt nach Authentifizierung... wie beschrieben den include:
include(ROOTPATH.$modulname."/".$groupname.".".$scriptname.".php");
Dann wird das was im Script steht ausgeführt. Was sollen jetz noch die USer-Rechte?
_Vor_ dem Include werden noch alle modul.setup.php-Dateien geladen und entsprechend das Menü erzeugt, und von mir aus ein Array mit Benutzerrechten, aber was bringt das an dieser Stelle?
- Müssen Module unabhängig von der Basisvwersion hinzufügbar und entfernbar sein. Die Module können auf alle 4 Benutzergruppen-eigene Seiten Einfluß haben, ob jetzt Menüstruktur, extra Seiten/-Funktionalitäten, Datenbank-Tabellen...
Module sollte erst einmal unabhängig vom Menü sein. Du solltest in einer Menüverwaltung die Module manuell mit einem Menüpunkt verknüpfen können. (Genaugenommen speicherst Du dann einen Pfad zum Menüpunkt, der dann verlinkt wird)
Wieso? Alle notwendigen Module-setup-Dateien werden geladen, alle haben bestimmte Methoden aus denen sich dann das genamte Menü und die Nutzerrechte zusammensetzen, vollautomatisch. Warum nicht? Ich hatte damals CK so verstanden das ich das genau so machen soll.
und wenn ich es entferne verschinden die Funktionalitäten und Menüpunkte wieder. Sicher sinddas noch ein paar Kleinigkeiten die ich noch nicht im Detail geplant habe, aber ich denke das müßte ich so hinbekommen.
Schlechte Idee, siehe einen Absatz höher.
Aber gerade das will ich doch! Wo soll das Problem sein? Wennich 1000 Eisntellungen vornehmen muß, dann kann ich das in ein paar Monaten nicht mehr nachvollziehen, udn jemand anders überhaupt nicht, ich hatte nicht vor 250 Seiten Dokumentation zu schreiben ;-)
Vermutlich mache ich ein "add.module.fragebogengenerator.php" -Script, welches alle Einstelluneg vornimmt, und genauso "delete.module.fragebogengenerator.php" welches alles wieder entfernt.
Schlechte Idee. Im Prinzip sollte ein Modul (oder Untermodul oder wie Du es organisierst) eine Datei sein. Diese Datei musst Du hochladen. Dann steht das Modul in der Administration zur Verfügung. In der Administration kannst du das Modul dann einrichten. Wenn das Modul Tabellen braucht, dann hast Du noch 2 zusätzliche SQL-Scripte, die Du dann einspielen kannst - eines, um die erforderlichen Tabellen zu erstellen und eines, um sie wieder zu löschen. Diese solltest Du auch manuell einspielen. (evtl. über ein Administrationsinterface, aber immer noch manuell)
Hm. Hast Recht, mit so einem Admin-Menü wäre auch noch eine Möglichkeit. Aber sprechend wir besseer von plugins als von Modulen, ich habe das gefühl das wir unter "modul" nicht dasellbe verstehen.
Jedenfalls hast Du es mal wieder geschafft mich ordentlich zu verwirren und aufzuhalten ;-)
Aber genau das wollte ich ja, da ich weiß das es halt noch weit davon entfernt ist gut zu ein, also Danke für Deine Mühe und Geduld mit mit ;-)
Grüße
Andreas
Hallo Andreas,
Was heißt kenne? Ich habe mich schonmal als User unter Win2K oder Linux eingewählt,
Ähm, ich sollte vielleicht dazu sagen, dass Access Control Lists bei Linux erst ab Kernel 2.5.irgendwas von Haus aus (ohne Kernel-Patch) unterstützt werden. (und das auch nur im Kernel, die Anwendungen müssen das dann natürlich auch noch unterstützen) Das UNIX-Dateirechteprinzip ist simpler, aber bis zu einem gewissen Grade genauso effektiv. (nur wenn es wirklich komplizierte Rechteverteilungen gibt, dann versagt es, bzw. man muss sich etwas einfallen lassen)
sowas in der Art hätte ich auch gerne, nur habe ich zur Zeit das Problem, das sich mindestens 5 wirklich umfassende neue Gebiete alle gleichzeitig in einem Projekt das erste mal ausprobiere, bzw. versuche zu verstehen, das wird mir langsam alles zu kompliziert, ich blicke jetzt schon kaum noch durch, eben weil das so viele unbekannte Techniken sind, noch sowas kann ich zur Zeit glaube ich nicht mehr verkraften denn die Entwicklung wird auch immer langsamer dadurch.
Das ist natürlich ein Problem... :-(
Ich mache ja ein Login. ich habe 2 Tabellen:
- Tabelle: "User" mit den Spalten "UserID","GroupID", "Username", "Password", "Status"(damit kann ich einen User sperren)
- Tabelle: "Groups" mit den Spalten "GroupID", "GroupName", "Status"(damit kann ich eine Gruppe sperren)
Ich habe das so realisiert: Es gibt pro Objektart eine zusätzliche Tabelle, die die Rechte für jedes Objekt entählt. Beispiel anhand der Menüstruktur:
Tabelle menu: menuid, text, uri (vereinfacht)
Tabelle menu_acl: menuid, idtype, id, allow_access
Der Primärschlüssel erstreckt sich über menuid, idtype und id.
idtype kann bei mir entweder 1 (Gruppe) oder 2 (Benutzer) sein. id enthält dann die zugehörige Benutzer/GruppenID (ist mir egal, ob das gut normalisiert ist, mir ist nichts einfacheres eingefallen) Ich mache mal ein Beispieleintrag:
Tabelle users (vereinfacht)
----------------------------------------
userid groupid username
66 40 andreas
Tabelle groups (vereinfacht)
----------------------------------------
groupid groupname
40 admins
Tabelle menu (vereinfacht)
--------------------------------------------------
menuid text uri
3 Benutzerverwaltung /admin/user
Tabelle menu_acl
-------------------------------------------------------
menuid idtype id allow_access
3 1 40 TRUE
Folglich wird jedem Benutzer der Gruppe (idtype=1) 'admins' (id=40) der Zugriff auf den Eintrag 'Benutzerverwaltung' (menuid=3) erlaubt. (allow_access=TRUE) Somit kannst Du natürlich beliebig viele Rechteverknüpfungen hinzufügen. Police: Was nicht explizit erlaubt ist, ist verboten.
Bei mir sind es grundverschiedene Menüs, mit genau gegensätzlichen Funktionen.
Das wäre auch mit so einer Rechteverwaltung, wie ich sie beschrieben habe, zu lösen. IMHO wäre es aber sinnvoller, eine m:n und nicht eine 1:n-Beziehung zwischen Benutzern und Gruppen herzustellen. Damit kannst Du Rechte noch feiner vergeben.
ich nenne sie nur so da ich persönlich den Begriff passender finde.
ACK. ;-)
Wie würde denn so eiej Rechtevergae jetzt praktisch aussehen? Mein modul.setup.php Script enthält jetzt z.B. eine Klasse in der Methoden stehen aus denen sich das Basisscript Infos zur Navigationsleirste holen soll, genauso könnte da eine Methode für Rechtevergabe stehen.
Auch. Aber eine ausgeklügelte Rechtevergabe bezieht sich auf _so gut wie jedes_ »Objekt« in der Datenbank. Nicht nur Menüeinträge, sondern auch Module (damit diese nicht manuell aufgerufen werden können) und bestimmte Aktionen in Modulen, desweiteren auch noch andere Dinge, wie z.B. Fragebögen selbst. Ist ein ziemlich großer Aufwand, ich weiß, aber es lohnt sich.
Nur was genau sollte die machen? Sicher kein Problem, einfach sagen wer Zugriff hat und wer nicht, z.B. in dem die Methode einen Array zurückgibt mit
array("lieferanten => true, "admin" => false...);
Nein. Es ist immer sinnvoller, eine Funktion zu verwenden, die für den _aktuellen_ Benutzer die Rechte zurückliefert. Dann kann das Script entscheiden, ob die vom Benutzer geforderte Funktionalität darunter fällt und wenn nicht => "Forbidden" o.ä. ;-)
Wieso? Alle notwendigen Module-setup-Dateien werden geladen, alle haben bestimmte Methoden aus denen sich dann das genamte Menü und die Nutzerrechte zusammensetzen, vollautomatisch. Warum nicht? Ich hatte damals CK so verstanden das ich das genau so machen soll.
Naja, ich habe andere Vorstellungen, als CK. :-) Ist ja auch gut so, denn wenn jeder alles gleich manchen würde, dann gäbe es keinen Fortschritt und keine Innovation. Aber Du kannst es ruhig so machen, wie CK.
Aber gerade das will ich doch! Wo soll das Problem sein? Wennich 1000 Eisntellungen vornehmen muß, dann kann ich das in ein paar Monaten nicht mehr nachvollziehen, udn jemand anders überhaupt nicht, ich hatte nicht vor 250 Seiten Dokumentation zu schreiben ;-)
Hmmm. Also bei so einem Projekt, wie Du es vorhast, würde ich sagen, wären 50 Seiten Minimum, am besten 100, wenn jemand anderes damit klarkommen soll, ohne, dass er/sie Dich kennt. Wenn die Doku nur für Dich ist, dann können es natürlich weniger sein. Es gibt so einen blöden Spruch: »Eine Software ist nur so gut wie ihre Dokumentation.«
Hm. Hast Recht, mit so einem Admin-Menü wäre auch noch eine Möglichkeit. Aber sprechend wir besseer von plugins als von Modulen, ich habe das gefühl das wir unter "modul" nicht dasellbe verstehen.
Doch, wir verstehen glaube ich dasselbe. Plugins halt.
Jedenfalls hast Du es mal wieder geschafft mich ordentlich zu verwirren und aufzuhalten ;-)
Bedenke immer, (das habe ich doch schon mal gesagt, oder?) dass ich meinen eigenen Stil habe. Du kannst auch Deinen eigenen Entwickeln. Von daher: Ich habe überhaupt nichts dagegen, wenn Du etwas konzeptionell komplett anders machst, als ich. Solange es funktioniert... :-)
Grüße,
Christian
Hi Christian!
Ähm, ich sollte vielleicht dazu sagen, dass Access Control Lists bei Linux erst ab Kernel 2.5.irgendwas von Haus aus (ohne Kernel-Patch) unterstützt werden.
Ich hatte das nur gschrieben da ich die Techniken im Hintergrund nicht kenne, sondern nur als Anwender.
[...] das wird mir langsam alles zu kompliziert, ich blicke jetzt schon kaum noch durch [...]
Das ist natürlich ein Problem... :-(
Naja, wenn schon denn schon, jetzt habe ich mal angefangen dann will ich es jetzt vernünftig haben,m der Rest hat ja auch irgendwie merh oder weniger geklappt, und so langsam bekommt man auch allgemein ein besseres Verständnis für derartige Techniken, was nicht heißt das ich es alles verstehen würde.... :)
Jedenfalls Binde ich jetzt auch noch direkt ein komplexes Error-Handling mit ein(siehe [pref:t=34111&m=185654]),
btw: Wie hast Du das bei Dir gelöst?
aber zurück zum Thema:
Ich habe das so realisiert: Es gibt pro Objektart eine zusätzliche Tabelle, die die Rechte für jedes Objekt entählt. Beispiel anhand der Menüstruktur:
[...]
Folglich wird jedem Benutzer der Gruppe (idtype=1) 'admins' (id=40) der Zugriff auf den Eintrag 'Benutzerverwaltung' (menuid=3) erlaubt. (allow_access=TRUE) Somit kannst Du natürlich beliebig viele Rechteverknüpfungen hinzufügen. Police: Was nicht explizit erlaubt ist, ist verboten.
Puh, sowas hatte ich noch gar nicht in Betracht gezogen! Wobei ich diese Informationen ja nicht in der Datenbank speichern muß, ich habe ja auch ein Script "menu.php", welches das menü erzeugt. Ich hatte das jetzt so gedacht, dass sich dieses Script aus den verschiedenen Modulen oder Basis-Scripten die Informationen holt, die Du in der DB stehen hast. Das heißt alle Scripte die "menu.php" abfragt geben einen Menüeintrag und eine Rechte-Definition zurück, entsprechend des User-Gruppe, also ob Admin oder Lieferant werden ja jeweils andere Scripte abgefragt, also bekomme ich andere Menüstrukturen, Links und Rechte. In der Datenbank speichere ich wie gesagt nur die User und Gruppen. Muß mal überlegen ob das nicht vielleicht auch Sinn macht das in die Datenbank zu verlagern. Aber ich werde das vermutlich auch in Form einer eigenen Klasse bzw. eines internen Moduls(kein Plugin, so langsam versteh ich die Nomenklatur ;-)), so kann ich das auch nachher ändern.
Schwierig, schwierig. Aber ich mache mir sowieso langsam sorgen das mein Code zu kompex wird, wo frühr ein keines Script mit 100 Zeilen reichte lade ich mein Basismodul, da rein alle notwendigen Modul-Scripte, PEAR, SMARTY, Config-File, das eigentliche Script, das HTML-Template, die notwendigen Language-Files... das macht mir langsam Angst :o
Kann man irgendwie in PHP ermitteln wieviel Zeilen Code bei einem Script insgesamt geparst und ausgeführt werden? Würde mich mal interessieren!
ch hoffe das ganez bremst die Performance nicht zu sehr!
Das wäre auch mit so einer Rechteverwaltung, wie ich sie beschrieben habe, zu lösen. IMHO wäre es aber sinnvoller, eine m:n und nicht eine 1:n-Beziehung zwischen Benutzern und Gruppen herzustellen. Damit kannst Du Rechte noch feiner vergeben.
Das brau8che ich eigentlich nicht, ein Benutzer ist immer nur in einer Gruppe. Denn wenn ich das machen würde könnte ich nicht emrh ermiteln in welcher Gruppe der User ist, und müßte das dann anders ermitteln, OK, das ginge wohl durch einen Partameter im Anmeld-Script, aber das hat ja weitreichede Folgen, ich will nicht Flexibilität um jeden preis, denn je flexibler das ganze wird desto komplizierter wird es, und wie gesagt, der Grad an Koplexität ist schon jetzt nah dran mich zu überfordern ;-)
ich nenne sie nur so da ich persönlich den Begriff passender finde.
ACK. ;-)
oder doch nicht -> s.o. ;-)
Bedenke immer, (das habe ich doch schon mal gesagt, oder?) dass ich meinen eigenen Stil habe. Du kannst auch Deinen eigenen Entwickeln. Von daher: Ich habe überhaupt nichts dagegen, wenn Du etwas konzeptionell komplett anders machst, als ich. Solange es funktioniert... :-)
Das weiß ich sehr wohl, aber das was Du mir schreibst ist mal so eine Richtung die halt funktioniert, wenn ich alleien da sitze denke ich die meiste Zeit im Kreis udn habe oft bei scheinbar einfachen Dingen keine Ahnung wie ich das nur im entferntesten umsetzen könnte. Wenn Du ein Beispiel gibts bekomme ich meist eine Idee die in mein Konzept passt, auch wenn es was ganz anderes ist als Du gemeint hast, meist reicht eine bestimmte Denkweise, wo man aber durch Nachdenken nicht selbst drauf kommt, ich zumindest nicht.
Also nochmals vielen Dank!
Viele Grüße
Andreas