Question

Quel est l'avantage d'utiliser singleton au lieu de global pour les connexions à une base de données en PHP? Je pense que l’utilisation de singleton au lieu de global rend le code inutilement complexe.

Code avec global

$conn = new PDO(...);

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

Code avec 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();
    .
    .
    .
}

S'il existe un meilleur moyen d'initialiser une connexion à une base de données autre que global ou singleton, veuillez en faire mention et décrire ses avantages par rapport à global ou singleton.

Était-ce utile?

La solution

Je sais que c'est vieux, mais la réponse de Dr8k était presque .

Lorsque vous envisagez d'écrire un morceau de code, supposez qu'il va changer. Cela ne signifie pas que vous supposez le type de changements qu'il y apportera à l'avenir, mais plutôt qu'une forme de changement sera apportée.

Fixez-vous un objectif pour atténuer les difficultés liées aux changements à venir: un global est dangereux car il est difficile à gérer en un seul endroit. Que faire si je souhaite que le contexte de connexion à la base de données soit conscient à l'avenir? Et si je veux qu'il se ferme et se rouvre tous les 5 ans, il a été utilisé. Que faire si je décide que, dans l’intérêt de redimensionner mon application, je veux utiliser un pool de 10 connexions? Ou un nombre configurable de connexions?

Une fabrique de singleton vous offre cette flexibilité. Je l'ai configuré avec très peu de complexité supplémentaire et j'obtiens plus qu'un simple accès à la même connexion; Je gagne la possibilité de changer la manière dont cette connexion m'est transmise plus tard, de manière simple.

Notez que je dis singleton factory par opposition à simplement singleton . Il y a peu de différence entre un singleton et un global, c'est vrai. Et à cause de cela, il n’ya aucune raison d’avoir une connexion singleton: pourquoi voudriez-vous passer le temps de le configurer pour pouvoir créer un global régulier?

Ce qu’une fabrique vous procure, c’est pourquoi vous obtenez des connexions et un emplacement séparé pour décider de la ou des connexions (s) que vous obtiendrez.

Exemple

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();
    .
    .
    .
}

Puis, dans 6 mois, lorsque votre application sera très célèbre et qu’elle aura besoin de plus d’une connexion, il vous suffira d’implémenter un certain pooling dans la méthode getConnection (). Ou si vous décidez que vous voulez un wrapper qui implémente la journalisation SQL, vous pouvez passer une sous-classe PDO. Ou si vous décidez que vous voulez une nouvelle connexion à chaque appel, vous pouvez le faire. C'est flexible, au lieu d'être rigide.

16 lignes de code, y compris les accolades, vous feront économiser des heures et des heures et des heures de refactorisation à quelque chose de terriblement similaire sur toute la ligne.

Notez que je ne considère pas ce " Feature Creep " parce que je ne fais aucune implémentation de fonctionnalité dans le premier tour. C'est une ligne frontière "Future Creep", mais à un moment donné, l'idée que "coder pour demain aujourd'hui" Est-ce que toujours une mauvaise chose ne me dérange pas?

Autres conseils

Je ne suis pas sûr de pouvoir répondre à votre question précise, mais je voulais suggérer que les objets de connexion global / singleton ne sont peut-être pas la meilleure idée si cela s'applique à un système basé sur le Web. Les SGBD sont généralement conçus pour gérer efficacement un grand nombre de connexions uniques. Si vous utilisez un objet de connexion global, vous devez alors effectuer quelques opérations:

  1. Vous obliger les pages à faire toute la base de données connexions séquentiellement et tuer toute tentative de page asyncrone charges.

  2. Maintien potentiel des verrous ouverts éléments de base de données plus longs que nécessaire, ralentissement général performances de la base de données.

  3. Augmenter le nombre total de connexions simultanées votre la base de données peut supporter et bloquer les nouveaux utilisateurs d'accéder à la ressources.

Je suis sûr qu'il y a également d'autres conséquences potentielles. N'oubliez pas que cette méthode tentera de maintenir une connexion à la base de données pour chaque utilisateur accédant au site. Si vous avez seulement un ou deux utilisateurs, ce n'est pas un problème. S'il s'agit d'un site Web public et que vous souhaitez obtenir du trafic, l'évolutivité deviendra un problème.

[MODIFIER]

Dans les situations à plus grande échelle, la création de nouvelles connexions chaque fois que vous frappez la base de données peut être mauvaise. Cependant, la solution n'est pas de créer une connexion globale et de la réutiliser pour tout. La réponse est le regroupement de connexion.

Avec le regroupement de connexions, un certain nombre de connexions distinctes sont conservées. Lorsqu'une connexion est requise par l'application, la première connexion disponible du pool est extraite, puis restituée au pool une fois son travail terminé. Si une connexion est demandée et qu'aucune n'est disponible, l'une des deux choses suivantes se produira: a) si le nombre maximal de connexions autorisées n'est pas atteint, une nouvelle connexion est ouverte ou b) l'application est obligée d'attendre qu'une connexion soit disponible. .

Remarque: dans les langues .Net, le regroupement de connexions est géré par défaut par les objets ADO.Net (la chaîne de connexion définit toutes les informations requises).

Merci à Crad pour ses commentaires.

La méthode singleton a été créée pour s’assurer qu’il n’y avait qu’une instance de toute classe. Mais, parce que les gens l’utilisent comme un moyen de raccourcir la mondialisation, on l’appelle programmation paresseuse ou mauvaise.

Par conséquent, j'ignorerais Global et Singleton, car les deux ne sont pas vraiment la POO.

Vous recherchiez une injection de dépendance .

Vous pouvez consulter des informations faciles à lire sur PHP relatives à l'injection de dépendance (avec des exemples) à l'adresse http://components.symfony-project.org/dependency-injection/trunk/book/01-Dependency-Injection

Les deux modèles produisent le même effet net, fournissant un seul point d'accès pour vos appels de base de données.

En termes d’implémentation spécifique, le singleton a le petit avantage de ne pas établir de connexion à une base de données tant que l’une au moins de vos autres méthodes n’a pas demandé. En pratique, dans la plupart des applications que j'ai écrites, cela ne fait pas une grande différence, mais c'est un avantage potentiel si vous avez des pages / chemins d'exécution qui ne font aucun appel à la base de données, car ces pages ne le feront pas. jamais demander une connexion à la base de données.

Une autre différence mineure est que l'implémentation globale peut piétiner involontairement d'autres noms de variables dans l'application. Il est peu probable que vous déclariez accidentellement une autre référence globale $ db, bien qu'il soit possible de l'écraser accidentellement (par exemple, vous écrivez si ($ db = null) alors que vous vouliez écrire si ($ db == null). L'objet singleton empêche cela.

Si vous n'utilisez pas une connexion persistante et qu'il existe des cas de refus, je trouve qu'un singleton est plus acceptable d'un point de vue conceptuel qu'un design global en mode OO.

Dans une véritable architecture OO, un singleton est plus efficace que de créer une nouvelle instance de l'objet à chaque fois.

Sur l'exemple donné, je ne vois aucune raison d'utiliser des singletons. En règle générale, si mon seul souci est d'autoriser une seule instance d'un objet, si le langage le permet, je préfère utiliser des éléments globaux

En général, j'utiliserais un singleton pour une connexion à une base de données ... Vous ne voulez pas créer une nouvelle connexion à chaque fois que vous devez interagir avec la base de données ... Cela pourrait nuire aux performances et à la bande passante de votre réseau ... Pourquoi en créer un nouveau, quand il y en a un de disponible ... Juste mes 2 centimes ...

RWendi

C'est assez simple. Ne jamais utiliser global OR Singleton.

Comme conseils, singleton et global sont valides et peuvent être associés au même système, projet, plug-in, produit, etc. . . Dans mon cas, je fabrique des produits numériques pour le Web (plug-in).

J'utilise uniquement singleton dans la classe principale et je l'utilise par principe. Je ne l'utilise presque pas parce que je sais que la classe principale ne l'instanciera plus.

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

Utilisation globale pour presque toutes les classes secondaires, exemple:

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

lors de l'exécution, je peux utiliser Global pour appeler leurs méthodes et leurs attributs dans la même instance car je n'ai pas besoin d'une autre instance de ma classe de produits principale.

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

Avec Global, on utilise la même instance pour pouvoir faire fonctionner le produit car je n’ai pas besoin d’une fabrique pour les instances de la même classe, elle est généralement destinée à de grands systèmes ou à de très rares objectifs.

En conclusion: , si vous avez déjà bien compris, vous devez utiliser l'anti-pattern Singleton et comprendre le Global , vous pouvez utiliser Une des 2 options ou les mélanger mais si je recommande de ne pas abuser car il y a beaucoup de programmeurs très exceptionnels et fidèles à la programmation orientée objet, utilisez-le pour les classes principales et secondaires que vous utilisez beaucoup pendant le temps d'exécution. (Cela vous fait économiser beaucoup de temps processeur). & # 128521;

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top