mmofacts.com

Singelton Pattern in PHP

gepostet vor 17 Jahre, 5 Monate von Agmemon
Ich bräuchte mal eure Hilfe bei einer PHP5 Geschichte. Zur Zeit experimentiere ich ein wenig mit Enterprise-Pattern und derer Implementierung in PHP herum.
Ich versuche mal den Call-Stack zu verdeutlichen, damit meine Frage gleich besser verständlich ist. Die Datei, welche vom Browser aufgerufen wird, sieht wie folgt aus:
	require_once 'lib/admin_controller.php';


$controller = new AdminController();
$controller->execute($_REQUEST);
?>
Die Klasse AdminController, implementiert das FrontController Pattern. Mehr dazu gleich. Der Execute-Methode werden über $_Request, alle Eingabedaten übergeben. Innerhalb der Methode werden diese dann in Form eines Objektes gekapselt, welches das RequestHelper Pattern implementiert:
public function execute($request) {

$input = new RequestHelper($request);

$this->initApplication();
$this->handleRequest($input);
}
Der FrontController verfügt über ein Mapping zwischen Kommando-Namen und Klassen. In der Methode handleRequest, wird aus dem RequestHelper Objekt der Name des Kommandos bestimmt, die zugehörige Kommando-Klasse instanziert und die weitere Arbeit an das neu erstellte Objekt übergeben.
Die jeweiligen Kommandoklassen enthalten also die Geschäftslogik, die ihrerseits wieder auf weitere Klassen und Objekt zugreift.
Jetzt zu meiner Frage:
Mir ist es eigentlich zu doof, das RequestHelper-Objekt ständig durch zu reichen, was ich machen müsste, da alle beteiligten Klassen darauf zugreifen können müssen, da hier alle Eingabedaten, Ausgabedaten und Fehler drin gesammelt werden. Jetzt ist meine Überlegung, den RequestHelper einfach als Singelton zu implementieren. Da es aber beim Singelton immer mal zu Problemen kommen kann, je nachdem in welcher Umgebung man es verwendet, ist meine Frage, ob es mit Singeltons in PHP irgendwelche Probleme geben kann? Ist es sichergestellt, dass das RequestHelper Objekt immer nur im Kontext seines Benutzers vorhanden ist?
Freue mich auf Eure Einschätzung/Erfahrung.
gepostet vor 17 Jahre, 5 Monate von Itchy
Ich verstehe nicht so ganz, was das Problem sein soll? Meinst Du evtl. ein Synchronisationsproblem?
Wenn das RequestHelper-Objekt ein Singleton innerhalb einer (Benutzer-)-Session sein soll, dann sollte es keine Probleme geben, schließlich kennt PHP5 ja keine Threads und daß die Sessions gegeinander abgeschottet sind, darf man hoffentlich voraussetzen.
Willst Du ein globales (applikationsweites) Singleton-Objekt haben, braucht Du zur Erzeugung einen entsprechenden Sperrmechanismus. Dazu bieten sich Betriebssystem-Sperren an (flock, Semaphoren) oder auch Sperren in einer Datenbank.
gepostet vor 17 Jahre, 5 Monate von Nuky
Meinst du die ineffizienz?
...weitergeben als referenz? Damit erstellst du nicht jedes mal eine neue Kopie davon.. oder steh ich vollkommen im Wald?
gepostet vor 17 Jahre, 5 Monate von Toby
In PHP5 wird jedes Objekt als Referenz weitergegeben, will man es kopieren muss man es klonen.
Ich hab bisher mit Singletons keine Probleme gehabt, selbst wenn es in der Session gespeichert ist.
Wenn die Sessions sauber getrennt sind gibt es auch keine Probleme mit dem Benutzerkontext.
Wo man Probleme haben könnte, ist, wenn man mit Vererbung arbeitet.
Ich hatte zwei Klassen von einer abstrakten abgeleitet und die Variable die das Singleton beinhaltet hatte war in dieser abstrakten Klasse definiert. Ergebnis war, das ich nur eine der zwei Klassen instanzieren konnte.
gepostet vor 17 Jahre, 5 Monate von Agmemon
Das Umfeld schön erklärt, aber die eigentliche Frage in den Sand gesetzt.
Das Singelton-Pattern ist ja dafür da, das es von der betreffenden Klasse in der ganzen Anwendung nur eine Instanz gibt. Wenn ich jetzt meine PHP Anwendung in Form von FastCGI laufen lasse, kann ich das Singelton-Pattern nicht nutzen, da ich damit in Gefahr laufen würde, das User2 im RequestHelper Daten von User1 haben könnte.
Ich war jetzt am Überlegen, ob es ein ähnliches Problem geben könnte, wenn die Anwendung als mod_php läuft. Also ob sicher gestellt ist, das unter Apache mit mod_php jeder Request wirklich als eigenständige Anwendungsinstanz gehandhabt wird und das Singelton wirklich immer nur für einen Request gilt.
@Nuky: das mit der Referenz ist klar. Ich müsste das RequerstHelper Objekt nur jedes mal an so ziemlich alle Methoden übergeben. Und da der Call-Stack nicht gerade klein ist, war ich am Überlegen, ob es mit einem Singelton nicht etwas eleganter ist, auch wenn es vielleicht das Pattern etwas missbraucht.
gepostet vor 17 Jahre, 5 Monate von shadows
Wie du schon gesagt hast ist das Singleton Pattern dafür gedacht das man genau eine Instanz in der Anwendung hat. Daher ist es nicht wirklich für deinen Anwendungszweck gedacht. Auch wenn man vielleicht durch irgendwelche Trickserei es dazu verwenden kann würde es doch Verwirrung schaffen.
Zu beachten bei dem Singleton Pattern ist der Speicherverbrauch. Die Daten die dort gespeichert werden "leben" solange die Anwendung lebt!
Ich verwende das Pattern für allgemeine Daten wie die Systemvariablen. Dadurch brauche ich die nur beim Start der Anwendung einmal aus der Datenbank laden und kann sie für alle Nutzer verwenden.
Gruß
shadows
gepostet vor 17 Jahre, 5 Monate von Agmemon
OK, ich versuche es mal andersrum:
CGI:
Beim Request wird im Webserver der zuständige Interpreter geladen und das Script abgearbeitet. Mit Beendigung des Requests, verschwinden Interpreter und Script aus dem Speicher. Bezogen auf das Singelton bedeutet das, dass es nur für die Dauer des Requests lebt.
FastCGI:
Interpreter und Script werden mit dem Starten des Webservers geladen und sind über die Request-Grenzen hinweg aktiv. Das Singelton würde im Speicher verbleiben.
Wie verhält es sich jetzt exakt bei mod_php?
gepostet vor 17 Jahre, 5 Monate von Toby
Nach meinen Erfahrungen existiert es bei mod_php nur für den aktuellen Request. Rufst du das Script nochmal auf wird ein neues Singleton-Objekt erzeugt.
Ich mache bei mir fast alles über Singletons und speichere sie teilweise auch in der Session. Ich hab eher Probleme damit das manchmal Daten nicht in der Session gespeichert werden aber noch nie das mir fremde Daten quergeschossen wären.
gepostet vor 17 Jahre, 5 Monate von Agmemon
Wunderbar, so hatte ich mir das erhofft. Schon erstaunlich, was für Lücken sich auftun, wenn man etwas lange Zeit nicht nutzt. Und da ich zuvor noch nie PHP5 verwendet habe, kamen solche Fragestellungen gar nicht erst auf, denn PHP4 und OO war ja nicht so prickelnd.

Auf diese Diskussion antworten