Frage

Was ist der Vorteil von Singleton anstelle von globalen für Datenbankverbindungen in PHP? Ich fühle mich Singleton anstelle von globalen macht den Code unnötig komplex.

-Code mit Global

$conn = new PDO(...);

function getSomething()
{
    global $conn;
    .
    .
    .
}

Code mit Singleton

class DB_Instance
{
    private static $db;

    public static function getDBO()
    {
        if (!self::$db)
            self::$db = new PDO(...);

        return self::$db;
    }
}

function getSomething()
{
    $conn = DB_Instance::getDBO();
    .
    .
    .
}

Wenn es eine bessere Art und Weise ist die Datenbankverbindung zu initialisieren andere als global oder Singleton, bitte erwähnen und die Vorteile beschreiben sie über globale oder Singletons haben.

War es hilfreich?

Lösung

Ich weiß, das ist alt, aber Dr8k Antwort war fast es.

Wenn Sie erwägen, ein Stück Code zu schreiben, nehme an, es ändern wird zu. Das bedeutet nicht, dass Sie die Art von Änderungen gehen davon aus es zu einem bestimmten Zeitpunkt in der Zukunft auf sie gehisst haben wird, sondern dass eine gewisse Form der Änderung vorgenommen wird.

Machen Sie es ein Ziel, den Schmerz zu machen Veränderungen in der Zukunft mildern: ein globalen gefährlich ist, weil es schwer ist, in einem einzigen Ort zu verwalten. Was passiert, wenn ich möchte, dass die Datenbankverbindung Kontext in Zukunft bewusst machen? Was passiert, wenn ich es selbst wurde jedes 5. Mal schließen möchten und öffnen Sie es verwendet. Was passiert, wenn ich entscheide, dass mein App im Interesse der Skalierung Ich mag einen Pool von 10 Verbindungen benutzen? Oder eine konfigurierbare Anzahl von Verbindungen?

Singleton Fabrik gibt Ihnen diese Flexibilität. Ich stellte es mit sehr wenig zusätzlicher Komplexität und mehr gewinne als nur auf den gleichen Anschluss zuzugreifen; Ich gewinne die Fähigkeit zu ändern, wie die Verbindung zu mir geführt wird später in einfacher Weise.

Beachten Sie, dass ich sage, Singleton Fabrik im Gegensatz zu einfach Singleton . Es gibt sehr wenig Unterschied zwischen einem Singleton und einem globalen, wahr. Und aus diesem Grund gibt es keinen Grund, eine Singleton-Verbindung haben: warum sollten Sie die Zeit einstellen, dass verbringen, wenn Sie stattdessen eine regelmäßige globale schaffen könnte

Was für eine Fabrik Sie bekommt, ist ein Grund-Verbindungen zu erhalten, und eine separate Stelle zu entscheiden, welche Verbindungen (oder Verbindung) Sie gehen zu bekommen.

Beispiel

class ConnectionFactory
{
    private static $factory;
    private $db;

    public static function getFactory()
    {
        if (!self::$factory)
            self::$factory = new ConnectionFactory(...);
        return self::$factory;
    }

    public function getConnection() {
        if (!$this->db)
            $this->db = new PDO(...);
        return $this->db;
    }
}

function getSomething()
{
    $conn = ConnectionFactory::getFactory()->getConnection();
    .
    .
    .
}

Dann in 6 Monaten, wenn Ihr App ist super berühmt und immer dugg und slashdotted und Sie entscheiden, Sie brauchen mehr als eine einzige Verbindung, alles, was Sie tun müssen, ist eine Bündelung in dem getConnection () -Methode zu implementieren. Oder wenn Sie entscheiden, dass Sie einen Wrapper möchten, die SQL-Protokollierung implementiert, können Sie eine PDO Unterklasse übergeben. Oder wenn Sie sich entscheiden, möchten Sie eine neue Verbindung bei jedem Aufruf, können Sie das tun. Es ist flexibel, statt starr.

16 Zeilen Code, einschließlich Klammern, die Ihnen Stunden und Stunden und Stunden von Refactoring etwas unheimlich ähnlich der ganzen Linie sparen.

Beachten Sie, dass ich nicht dieses „Feature Creep“ betrachten, weil ich keine Feature-Implementierung im ersten Go Runde machte. Es ist Grenzlinie „Future Creep“, aber irgendwann die Idee, dass „Codierung für morgen heute“ ist immer eine schlechte Sache für mich tut nicht jive.

Andere Tipps

Ich bin mir nicht sicher, ob ich Ihre Frage beantworten können, aber ich wollte, dass die globalen / Singleton Verbindungsobjekte die beste Idee, wenn diese Einstellung, wenn ein Web-basiertes System sein können, nicht vor. DBMS-Systeme sind in der Regel eine große Anzahl von einzigartigen Verbindungen auf effiziente Weise verwalten konzipiert. Wenn Sie ein globales Verbindungsobjekt verwenden, dann tun Sie ein paar Dinge:

  1. Erzwingen Sie Seiten alle Datenbank zu tun Verbindungen der Reihe nach und Töten alle Versuche, auf asynchroner Seite Ladungen.

  2. Potenziell offen halten Sperren auf Datenbankelemente länger als notwendig, eine Verlangsamung insgesamt nach unten Datenbank-Performance.

  3. Maxing die Gesamtzahl aus Ihre gleichzeitige Verbindungen Datenbank unterstützen kann und blockiert neue Benutzer vom Zugriff auf Ressourcen.

Ich bin sicher, es gibt auch andere mögliche Folgen. Denken Sie daran, diese Methode versuchen wird, eine Datenbankverbindung für jeden Benutzer zu erhalten Zugriff auf die Site. Wenn Sie nur einen oder zwei Benutzer haben, kein Problem. Wenn dies eine öffentliche Website und Sie mögen Verkehr dann wird die Skalierbarkeit zu einem Problem werden.

[EDIT]

In größeren skaliert Situationen, neue Verbindungen jedes Mal zu schaffen treffen Sie die datase schlecht sein kann. Allerdings ist die Antwort nicht eine globale Verbindung zu erstellen und es für alles wiederverwenden. Die Antwort ist, Connection Pooling.

Mit Verbindungs-Pooling, eine Anzahl verschiedener Verbindungen aufrechterhalten werden. Wenn eine Verbindung durch die Anwendung die erste verfügbare Verbindung aus dem Pool erforderlich ist, abgerufen und dann an den Pool zurückgegeben, sobald seine Arbeit erledigt ist. Wenn eine Verbindung angefordert wird und keine verfügbar sind eines von zwei Dingen geschehen wird: a) wenn die maximale Anzahl der erlaubten Verbindung nicht erreicht wird, wird eine neue Verbindung geöffnet wird, oder b) die Anwendung ist gezwungen, für eine Verbindung zu warten verfügbar zu werden .

Hinweis: In .NET-Sprachen, Connection Pooling von den ADO.Net Objekte standardmäßig (die Verbindungszeichenfolge setzt alle erforderlichen Informationen) behandelt wird.

Dank CRAD auf diese für die Kommentare.

wurde Die Singleton-Methode erstellt, um sicherzustellen, gibt es nur eine Instanz einer Klasse. Aber, weil die Menschen es als eine Möglichkeit, sich globalisierenden abzukürzen, wird es bekannt als faul und / oder schlechte Programmierung.

Deshalb würde ich global und Singleton ignorieren, da beide nicht wirklich OOP sind.

Was Sie suchen ist Dependency Injection .

Sie können auf einfache überprüfen PHP-basierte Informationen lesen im Zusammenhang Injektion Abhängigkeit (mit Beispielen) unter http://components.symfony-project.org/dependency-injection/trunk/book/01-Dependency-Injection

Beiden Muster erreichen den gleichen Netto-Effekt, einen einzigen Zugriffspunkt für Ihre Datenbank Anrufe bereitstellt.

Im Hinblick auf die speziellen Implementierung hat die Singletons einen kleinen Vorteil, nicht eine Datenbankverbindung, bis mindestens einer Ihrer anderen Methoden fordert sie initiieren. In der Praxis in den meisten Anwendungen, die ich geschrieben habe, bedeutet dies nicht viel Unterschied machen, aber es ist ein potenzieller Vorteil, wenn Sie einige Seiten / Ausführungspfade, die überhaupt nicht jede Datenbank-Anrufe, da diese Seiten nicht je fordern Sie eine Verbindung zur Datenbank.

Ein weiterer kleiner Unterschied besteht darin, dass die globale Implementierung unbeabsichtigt über andere Variablennamen in der Anwendung mit Füßen treten kann. Es ist unwahrscheinlich, dass Sie schon einmal versehentlich eine andere global $ db Referenz erklären werde, obwohl es möglich ist, dass man es versehentlich überschrieben werden könnten (zum Beispiel Sie schreiben if ($ db = null), wenn Sie if ($ db == null) schreiben bedeutete. das Singleton-Objekt verhindert das.

Wenn Sie nicht eine ständige Verbindung zu verwenden, gehen, und es gibt Fälle, für die das nicht tun, finde ich ein Singleton konzeptionell schmackhafter zu sein, als ein globales in OO-Design.

In einer echten OO-Architektur, ein Singleton ist wirksamer als eine neue Instanz jedes Mal das Objekt erstellen.

Auf dem gegebenen Beispiel sehe ich keinen Grund Singletons zu verwenden. Als Faustregel gilt: wenn meine einzige Sorge ist, eine einzelne Instanz eines Objekts zu ermöglichen, wenn die Sprache erlaubt es, ziehe ich es Globals verwenden

Im Allgemeinen würde ich einen Singleton für eine Datenbankverbindung verwenden ... Sie wollen nicht, ein neue Verbindung jedes Mal wenn Sie in die Datenbank zu interagieren müssen erstellen ... Dies könnte perfomance und Bandbreite des Netzwerks verletzt ... Warum eine neue erstellen, wenn gibt es noch eine vorhanden ... Just my 2 cents ...

RWendi

Es ist ganz einfach. Verwenden Sie niemals global oder Singleton.

Als Beratung sowohl Singleton und global sind gültig und können innerhalb des gleichen System, Projekt, plugin, Produkt, etc verbunden werden .. . In meinem Fall mache ich digitale Produkte für das Web (Plugin).

Ich verwende nur Singleton in der Hauptklasse und ich verwende es prinzipbedingt. Ich fast nicht verwenden, weil ich weiß, dass die Hauptklasse wird es nicht wieder instanziiert

<?php // file0.php

final class Main_Class
{
    private static $instance;
    private $time;

    private final function __construct()
    {
        $this->time = 0;
    }
    public final static function getInstance() : self
    {
        if (self::$instance instanceof self) {
            return self::$instance;
        }

        return self::$instance = new self();
    }
    public final function __clone()
    {
        throw new LogicException("Cloning timer is prohibited");
    }
    public final function __sleep()
    {
        throw new LogicException("Serializing timer is prohibited");
    }
    public final function __wakeup()
    {
        throw new LogicException("UnSerializing timer is prohibited");
    }
}

Globale Verwendung für fast alle Sekundärklassen, zB:

<?php // file1.php
global $YUZO;
$YUZO = new YUZO; // YUZO is name class

, während zur Laufzeit kann ich Globale ihre Methoden aufrufen und Attribute in der gleichen Instanz, weil ich eine andere Instanz meiner Hauptproduktklasse nicht brauchen.

<?php // file2.php
global $YUZO;
$YUZO->method1()->run();
$YUZO->method2( 'parameter' )->html()->print();

ich mit dem globalen bekommen, ist die gleiche Instanz zu verwenden, um der Lage sein, das Produkt der Arbeit zu machen, weil ich für Instanzen derselben Klasse nicht über eine Fabrik benötigen, in der Regel die Instanz-Factory ist für große Systeme oder für sehr seltene Zwecke.

In conclusion:, müssen Sie, wenn Sie bereits gut verstehen, dass die anti-Muster Singleton und verstehen, die Globale können Sie eine der zwei Optionen verwenden oder mischen sie aber wenn ich empfehle nicht zu missbrauchen, da es viele Programmierer, die sehr Ausnahme und getreu die Programmierung OOP sind, verwenden Sie es für Haupt- und Nebenklassen, die Sie viel in der Ausführungszeit verwenden. (Es spart Ihnen eine Menge CPU).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top