Die Verwendung von Globals macht Ihren Code schwer zu testen und ist daher anfälliger für Fehler, nicht sicher und unvorhersehbar. Deshalb übergeben wir die gewünschten Variablen innerhalb einer Funktion / eines Objekts. Meine Frage ist also einfach:
Verstoßen $ _POST, $ _GET usw. gegen das Kapselungsprinzip ?
Ich denke, um die Kontrolle über diese Variablen auf OO-Weise zu behalten, wäre es eine ideale Lösung, dem Code einige Zeilen wie diese hinzuzufügen:
// Convert the $_GET array to an object
$get = json_decode(json_encode($_GET), FALSE); // stackoverflow.com/a/1869147
// Stop it from being included from anywhere
unset($_GET);
// Small example of what could be done later on
$DB = new PDO(/* ... */);
$Person = new Person($DB, $get->id);
Ich habe das nirgendwo gesehen, nicht einmal ein Tutorial oder eine Empfehlung. Außerdem können wir deutlich sehen, dass der obige Code viel einfacher zu testen ist als einer, der ein $Person = new Person($DB, $_GET['id']);
oder sogar (das Hässliche) enthält, $Person = new Person($DB);
da Sie ein Scheinobjekt verwenden können $get
.
Ist der Code oben in die richtige Richtung oder fehlt mir etwas?
EDIT: Nach einigen Untersuchungen ( Zend Framework und Cake PHP ), wie Alexander Kuzmin vorgeschlagen hat, scheint es das Richtige zu sein. Sie sind wahrscheinlich zu groß für mich, um in den Code-Geldautomaten zu graben, aber ich werde es mir merken.
quelle
Antworten:
Ich bin mir nicht ganz sicher, warum Sie sich
json_decode
für$_GET
die Konvertierung in ein Array bewerben .$_GET
bereits ist ein Array.Verwendung der super-globals (
$_GET
,$_POST
etc) ist eine Verletzung der Einkapselung Prinzip. Aber es sollte eine Linie gezogen werden, in der Sie aufhören, Dinge zu kapseln. Anforderungsdaten sind ein guter Kandidat für die Einkapselung, aber lassen Sie sich nicht in den Kaninchenbau hineinziehen, wenn Sie versuchen, alle Dinge einzukapseln .Die meisten Frameworks verpacken normalerweise die Super-Globals von PHP in eine Art Anforderungsobjekt. Dies macht es dann einfacher, sich über Tests usw. lustig zu machen. Der einfachste Ansatz wäre:
Es ist einfach und rudimentär, macht aber den Job. Es ist auch ratsam, die Daten an dieser Stelle zu filtern, um sich gegen XSS-Injektionen zu verteidigen.
Aber es ist in ein
Request
Objekt eingewickelt . DasRequest
Objekt verfügt über vier Arrays, und diese Arrays können leicht verspottet werden:quelle
// Convert the $_GET array to an object
. Darüber hinaus ist diese Antwort stackoverflow.com/a/1869147 der Grund, warum ich es tue. Abgesehen von diesem kleinen Detail, vielen Dank für eine so vollständige Antwort mit zusätzlichen Tipps, die meiner Absicht sehr ähnlich ist.$_GET
Daten in ein Objekt konvertieren . Arrays sind nicht schmutzig. Ich habe das Gefühl, dass die Leute vor Arrays zurückschrecken, weil sie sich "nicht OOP" fühlen, so wie es niemand wagen würde, eine<table>
in HTML zu verwenden, aus Angst, selbst mit tabellarischen Daten unsemantisch zu sein. Nimm das$_GET
Array. Was passiert, wenn ich Array-Daten aus meinem Formular übergebe, dh<input type="checkbox" name="foo[]" />
oder<select name="bar[]" multiple="multiple">
? Wirst du sie in Objekte konvertieren oder so lassen, wie sie sind? Lassen Sie das$_GET
Array einfach wie vorgesehen als Array.GET
undPOST
Daten) haben, müssen sie wahrscheinlich kein Objekt sein.Die Verwendung von Superglobalen
$_{POST,GET,SERVER}
oder was auch immer verletzt sicherlich die Kapselung.Dieses Problem tritt auf, wenn Sie "lokale Anforderungen" auf der Serverseite Ihrer Anwendung erstellen möchten, wie dies heutzutage bei vielen Frameworks der Fall ist.
Ich bin es nicht gewohnt, mit Frameworks zu arbeiten, aber normalerweise erstelle ich zu Beginn meiner Verarbeitung ein Request / Response-Paar. Die Anfrage enthält die Werte dieser globalen Parameter.
Wenn ich eine serverseitige Unteranforderung erstellen möchte, habe ich zwei Möglichkeiten: Verwenden Sie den aktuellen Kontext oder erstellen Sie einen völlig neuen. Ich denke, Sie sollten diese superglobalen Variablen nicht deaktivieren, da Sie sie möglicherweise erneut verwenden möchten. Aus diesem Grund bin ich auch nicht der Meinung, dass Anforderungsparameter Singletons sein sollten.
Wenn nur Werte und keine Verweise auf diese Superglobalen enthalten sind, wirkt sich eine Änderung in einem Anforderungsobjekt niemals auf ein anderes aus. Daher ist das Problem mit dem globalen Status gelöst.
Grundsätzlich habe ich zwei Möglichkeiten:
quelle
POST- und GET-Variablen werden in einer Masse an den Server gesendet, und PHP muss einen Sinn daraus machen. In gewisser Weise ist es sinnvoll, sie global verfügbar zu haben, damit der Entwickler auswählen kann, wo sie verarbeitet werden sollen.
Viele Frameworks (wie z. B. CakePHP) lesen die Parameter und platzieren sie dann alle in einem Array, Objekt oder einer ähnlichen Struktur. Danach werden sie wie alle anderen Daten behandelt und an alle Methoden übergeben, die sie benötigen.
quelle
index.php
?Die Kapselung ist ein gutes Prinzip, wenn die Möglichkeit besteht, dass Sie mehrere Instanzen von etwas benötigen. Eine Webseite enthält jedoch nur einen Parametersatz. Wenn sie in einer Klasse statt in globalen Variablen wären, wären sie wahrscheinlich Singletons. Es gibt keine signifikante Verbesserung von globalen Variablen zu Singleton-Klassen, es ist nur eine andere Syntax, um auf sie zuzugreifen. Es handelt sich immer noch um von Natur aus globale Objekte. Dies ist nur umständlicher, da Sie die Klasseninstanz in den Griff bekommen und weitergeben müssen.
Da auf diese Parameter so häufig zugegriffen wird, haben die PHP-Designer beschlossen, den Zugriff auf sie zu vereinfachen, anstatt strenge Designprinzipien einzuhalten. Es ist eine gute Idee, die gängigsten Vorgänge bequem zu gestalten. Andernfalls verfluchen Sie Programmierer, weil sie jedes Mal dieselbe lange Sache erneut eingeben.
quelle
If they were in a class instead of global variables, they would probably be singletons
da Singletons ebenfalls im globalen Bereich liegen . Ich sage nur, dass dieser globale Staat vollständig gelöscht und lokalisiert werden soll, wobei diese Idee aus den Clean Code Talks - "Global State and Singletons" - übernommen wurde . Es ist mein Hauptanliegen, diese Frage zu stellen: Testen . Leider scheinen Sie nicht die ganze Frage gelesen zu haben, sondern nur den Titel$get
von Funktion zu Funktion weitergeben.