Frage Global oder Singleton für Datenbankverbindung?


Welchen Vorteil hat die Verwendung von Singleton statt Global für Datenbankverbindungen in PHP? Ich denke, Singleton anstelle von Global zu verwenden, 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 Möglichkeit gibt, eine Datenbankverbindung als Global oder Singleton zu initialisieren, erwähnen Sie sie bitte und beschreiben Sie ihre Vorteile gegenüber Global oder Singleton.


75
2017-09-25 00:56


Ursprung


Antworten:


Ich weiß, das ist alt, aber Dr8ks Antwort war fast Dort.

Wenn Sie darüber nachdenken, ein Stück Code zu schreiben, nehmen Sie an, dass es sich ändern wird. Das bedeutet nicht, dass Sie die Art von Änderungen annehmen, die es irgendwann in der Zukunft haben wird, sondern dass irgendeine Form von Veränderung vorgenommen wird.

Machen Sie es zu einem Ziel, mindern Sie den Schmerz, wenn Sie Änderungen in der Zukunft vornehmen: Ein Global ist gefährlich, weil es an einem einzigen Ort schwer zu verwalten ist. Was ist, wenn ich den Kontext dieser Datenbankverbindung in Zukunft bewusst machen möchte? Was, wenn ich möchte, dass es sich jedes fünfte Mal schließt und wieder öffnet, wenn es benutzt wurde. Was passiert, wenn ich beschließe, dass ich im Interesse der Skalierung meiner App einen Pool von 10 Verbindungen verwenden möchte? Oder eine konfigurierbare Anzahl von Verbindungen?

EIN Singleton Fabrik gibt Ihnen diese Flexibilität. Ich richte es mit sehr wenig zusätzlicher Komplexität ein und erhalte mehr als nur Zugriff auf dieselbe Verbindung; Ich bekomme später die Möglichkeit, auf einfache Weise zu ändern, wie diese Verbindung mir vermittelt wird.

Beachten Sie, dass ich sage Singleton Fabrik im Gegensatz zu einfach Singleton. Es gibt kaum einen kleinen Unterschied zwischen einem Singleton und einem globalen, wahren. Und deshalb gibt es keinen Grund, eine Singleton-Verbindung zu haben: Warum verbringst du die Zeit damit, das einzurichten, wenn du stattdessen ein reguläres globales erstellen kannst?

Was eine Fabrik Ihnen bringt, ist ein Grund, Verbindungen zu erhalten, und ein separater Ort, um zu entscheiden, welche Verbindungen (oder Verbindung) Sie bekommen werden.

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 Ihre App super berühmt ist und dugg und slashdotted ist und Sie entscheiden, dass Sie mehr als eine einzige Verbindung benötigen, müssen Sie nur ein paar Pooling in der getConnection () Methode implementieren. Wenn Sie sich für einen Wrapper entscheiden, der die SQL-Protokollierung implementiert, können Sie eine PDO-Unterklasse übergeben. Oder wenn Sie sich bei jedem Aufruf für eine neue Verbindung entscheiden, können Sie dies tun. Es ist flexibel, statt starr.

16 Zeilen Code, einschließlich Klammern, die Sie Stunden und Stunden und Stunden des Refactoring zu etwas gespenstisch ähnlichen auf der ganzen Linie sparen.

Beachten Sie, dass ich diesen Feature-Creep nicht betrachte, da ich in der ersten Runde keine Feature-Implementierung mache. Es ist Grenzlinie "Future Creep", aber irgendwann ist die Idee, "Codierung für morgen heute" immer eine schlechte Sache jive für mich nicht.


104
2017-10-20 19:37



Ich bin mir nicht sicher, ob ich Ihre spezifische Frage beantworten kann, wollte aber vorschlagen, dass globale / Singleton-Verbindungsobjekte möglicherweise nicht die beste Idee sind, wenn dies für ein webbasiertes System wäre. DBMS sind im Allgemeinen dafür ausgelegt, eine große Anzahl von eindeutigen Verbindungen auf effiziente Weise zu verwalten. Wenn Sie ein globales Verbindungsobjekt verwenden, tun Sie ein paar Dinge:

  1. Erzwingen Sie Ihre Seiten für die gesamte Datenbank Verbindungen nacheinander und töten alle Versuche auf asynchrone Seite Ladungen.

  2. Potenziell geöffnete Schlösser anbehalten Datenbankelemente länger als notwendig, verlangsamt insgesamt Datenbankleistung.

  3. Die Gesamtanzahl von gleichzeitige Verbindungen Datenbank kann unterstützen und blockieren neue Benutzer vom Zugriff auf die Ressourcen.

Ich bin mir sicher, dass es auch andere mögliche Konsequenzen gibt. Denken Sie daran, dass diese Methode versucht, eine Datenbankverbindung für jeden Benutzer aufrechtzuerhalten, der auf die Site zugreift. Wenn Sie nur ein oder zwei Benutzer haben, kein Problem. Wenn dies eine öffentliche Website ist und Sie Datenverkehr wünschen, wird die Skalierbarkeit zum Problem.

[BEARBEITEN]

In größeren Situationen kann das Erstellen neuer Verbindungen bei jedem Drücken der Daten falsch sein. Die Antwort besteht jedoch nicht darin, eine globale Verbindung zu erstellen und sie für alles wiederzuverwenden. Die Antwort ist Verbindungspooling.

Beim Verbindungspooling wird eine Anzahl eindeutiger Verbindungen aufrechterhalten. Wenn eine Verbindung von der Anwendung benötigt wird, wird die erste verfügbare Verbindung aus dem Pool abgerufen und dann in den Pool zurückgegeben, sobald der Job abgeschlossen ist. Wenn eine Verbindung angefordert wird und keine verfügbar ist, passiert eines von zwei Dingen: a) wenn die maximale Anzahl erlaubter Verbindungen nicht erreicht wird, wird eine neue Verbindung geöffnet, oder b) die Anwendung muss warten, bis eine Verbindung verfügbar wird .

Hinweis: In .Net-Sprachen wird das Verbindungs-Pooling standardmäßig von den ADO.Net-Objekten gehandhabt (die Verbindungszeichenfolge legt alle erforderlichen Informationen fest).

Danke an Crad für das Kommentieren.


15
2017-09-25 01:05



Die Singleton-Methode wurde erstellt, um sicherzustellen, dass es nur eine Instanz einer Klasse gibt. Aber weil die Leute es als eine Möglichkeit verwenden, die Globalisierung zu verkürzen, wird es als faule und / oder schlechte Programmierung bekannt.

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

Was du gesucht hast ist Abhängigkeitsspritze.

Sie können auf einfach zu lesende PHP-basierte Informationen zur Abhängigkeitsinjektion (mit Beispielen) nachsehen http://components.symfony-project.org/dependency- injection/trunk/book/01-Dependency-Injection


7
2017-12-13 00:35



Beide Muster erzielen denselben Nettoeffekt und stellen einen einzelnen Zugriffspunkt für Ihre Datenbankaufrufe bereit.

Im Hinblick auf die spezifische Implementierung hat das Singleton einen kleinen Vorteil, dass es keine Datenbankverbindung einleitet, bis mindestens eine Ihrer anderen Methoden es anfordert. In den meisten Anwendungen, die ich geschrieben habe, macht dies in der Praxis keinen großen Unterschied, aber es ist ein potenzieller Vorteil, wenn Sie einige Seiten / Ausführungspfade haben, die überhaupt keine Datenbankaufrufe machen, da diese Seiten dies nicht tun jemals eine Verbindung zur Datenbank anfordern.

Ein weiterer kleiner Unterschied besteht darin, dass die globale Implementierung unbeabsichtigt andere Variablennamen in der Anwendung übertreten kann. Es ist unwahrscheinlich, dass Sie jemals versehentlich eine andere globale $ db-Referenz deklarieren, obwohl es möglich ist, dass Sie sie versehentlich überschreiben könnten (zB wenn Sie if ($ db = null) schreiben, wenn Sie if ($ db == null) schreiben wollten. Das Singleton-Objekt verhindert das.


3
2017-09-25 02:44



Wenn Sie keine persistente Verbindung verwenden und es Fälle gibt, in denen dies nicht möglich ist, finde ich ein Singleton konzeptionell schmackhafter als ein globales OO-Design.

In einer echten OO-Architektur ist ein Singleton effektiver als das Objekt jedes Mal neu zu erstellen.


2
2017-09-25 01:03



Auf dem gegebenen Beispiel sehe ich keinen Grund, Singletons zu verwenden. Als Faustregel gilt, wenn es mir nur darum geht, eine einzelne Instanz eines Objekts zuzulassen, wenn es die Sprache erlaubt, verwende ich lieber globals


2
2017-09-25 01:06



Im Allgemeinen würde ich einen Singleton für eine Datenbankverbindung verwenden ... Sie möchten nicht jedes Mal eine neue Verbindung erstellen, wenn Sie mit der Datenbank interagieren müssen ... Dies könnte die Leistung und die Bandbreite Ihres Netzwerks beeinträchtigen ... Warum ein Neues, wenn es eins gibt ... Nur meine 2 Cent ...

RWendi


1
2017-09-25 01:14



Es ist ziemlich einfach. Verwenden Sie niemals globale ODER Singleton.


0
2017-09-25 00:59



Als Ratschlag beides Singleton und global sind gültig und können innerhalb derselben verknüpft werden System, Projekt, Plugin, Produkt, etc ... In meinem Fall mache ich digitale Produkte für das Web (Plugin).

Ich benutze nur Singleton in der Hauptklasse und ich benutze es grundsätzlich. Ich benutze es fast nicht, weil ich weiß, dass die Hauptklasse es nicht wieder instanziieren wird

<?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");
    }
}

Global Verwenden Sie für fast alle sekundären Klassen, Beispiel:

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

während zur Laufzeit kann ich verwenden Global um ihre Methoden und Attribute in derselben Instanz aufzurufen, weil ich keine andere Instanz meiner Hauptproduktklasse benötige.

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

Ich bekomme mit der globalen ist die gleiche Instanz zu verwenden, um das Produkt arbeiten zu können, weil ich keine Fabrik für Instanzen der gleichen Klasse benötigen, ist die Instanz Factory in der Regel für große Systeme oder für sehr seltene Zwecke.

In conclusion:Sie müssen, wenn Sie bereits gut verstehen, das ist das Anti-Muster Singleton und verstehe die GlobalSie können eine der 2 Optionen verwenden oder sie mischen, aber wenn ich empfehle, nicht zu missbrauchen, da es viele Programmierer gibt, die sehr Ausnahme sind und der Programmier-OOP treu sind, verwenden Sie sie für Haupt- und Sekundärklassen, die Sie innerhalb der Ausführung häufig verwenden Zeit. (Es spart Ihnen eine Menge CPU).


0
2018-05-27 18:36