Pregunta Global o Singleton para la conexión a la base de datos?


¿Cuál es el beneficio de usar singleton en lugar de global para conexiones de bases de datos en PHP? Siento que usar singleton en lugar de global hace que el código sea innecesariamente complejo.

Código con Global

$conn = new PDO(...);

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

Código con 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();
    .
    .
    .
}

Si hay una forma mejor de inicializar la conexión a la base de datos que no sea global o singleton, menciónelo y describa las ventajas que tiene sobre global o singleton.


75
2017-09-25 00:56


origen


Respuestas:


Sé que esto es viejo, pero la respuesta de Dr8k fue casi ahí.

Cuando considere escribir un fragmento de código, suponga que va a cambiar. Eso no significa que estés asumiendo los tipos de cambios que habrá provocado en algún momento en el futuro, sino que se realizará alguna forma de cambio.

Que sea un objetivo mitigar el dolor de hacer cambios en el futuro: un mundo es peligroso porque es difícil de manejar en un solo lugar. ¿Qué ocurre si quiero hacer que el contexto de conexión de la base de datos sea consciente en el futuro? ¿Qué sucede si quiero que se cierre y vuelva a abrirse cada 5ª vez que se usó? ¿Qué sucede si decido que, con el interés de escalar mi aplicación, quiero usar un conjunto de 10 conexiones? O una cantidad configurable de conexiones?

UN fábrica singleton te da esa flexibilidad. Lo configuré con muy poca complejidad adicional y obtuve más que solo el acceso a la misma conexión; Obtengo la habilidad de cambiar la forma en que se me pasa esa conexión más adelante de una manera simple.

Tenga en cuenta que digo fábrica singleton en lugar de simplemente semifallo. Hay muy poca diferencia entre un singleton y un global, cierto. Y debido a eso, no hay razón para tener una conexión singleton: ¿por qué pasar el tiempo configurando eso cuando podría crear un global regular en su lugar?

Lo que obtiene una fábrica es por qué obtener conexiones y un lugar aparte para decidir qué conexiones (o conexión) obtendrá.

Ejemplo

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

Luego, en 6 meses, cuando su aplicación sea súper famosa y obtenga Dugg y Slashdot, y usted decida que necesita más de una conexión, todo lo que tiene que hacer es implementar un agrupamiento en el método getConnection (). O bien, si decide que desea un contenedor que implemente el registro SQL, puede pasar una subclase PDO. O si decide que desea una nueva conexión en cada invocación, puede hacerlo. Es flexible, en lugar de rígido.

16 líneas de código, incluyendo llaves, que le ahorrarán horas y horas y horas de refactorización a algo inquietantemente similar en el futuro.

Tenga en cuenta que no considero este "Feature Creep" porque no estoy implementando ninguna función en la primera ronda. Es la línea fronteriza "Future Creep", pero en algún momento, la idea de que "la codificación para el mañana de hoy" es siempre una cosa mala no es para mí.


104
2017-10-20 19:37



No estoy seguro de poder responder a su pregunta específica, pero quería sugerir que los objetos de conexión global / singleton pueden no ser la mejor idea si esto es así para un sistema basado en la web. Los DBMS generalmente están diseñados para administrar grandes cantidades de conexiones únicas de manera eficiente. Si está utilizando un objeto de conexión global, entonces está haciendo un par de cosas:

  1. Forzándote páginas para hacer toda la base de datos conexiones secuencialmente y matar cualquier intento en una página asíncrona cargas.

  2. Potencialmente sosteniendo bloqueos abiertos en elementos de la base de datos más largos necesario, ralentizando en general rendimiento de la base de datos

  3. Maximizar el número total de conexiones simultáneas su la base de datos puede soportar y bloquear nuevos usuarios de acceder al recursos.

Estoy seguro de que hay otras posibles consecuencias también. Recuerde, este método intentará mantener una conexión de base de datos para cada usuario que acceda al sitio. Si solo tiene uno o dos usuarios, no hay problema. Si se trata de un sitio web público y desea tráfico, la escalabilidad se convertirá en un problema.

[EDITAR]

En situaciones escaladas más grandes, crear nuevas conexiones cada vez que acierte el datase puede ser malo. Sin embargo, la respuesta no es crear una conexión global y reutilizarla para todo. La respuesta es la agrupación de conexiones.

Con la agrupación de conexiones, se mantienen varias conexiones distintas. Cuando la aplicación requiere una conexión, la primera conexión disponible del grupo se recupera y luego se devuelve al grupo una vez que se realiza su trabajo. Si se solicita una conexión y no hay ninguna disponible, ocurrirá una de estas dos cosas: a) si no se alcanza la cantidad máxima de conexión permitida, se abre una nueva conexión, o b) la aplicación se ve obligada a esperar a que esté disponible una conexión .

Nota: En los lenguajes .Net, los objetos ADO.Net manejan la agrupación de conexiones de manera predeterminada (la cadena de conexión establece toda la información requerida).

Gracias a Crad por comentar sobre esto.


15
2017-09-25 01:05



El método singleton fue creado para asegurarse de que haya solo una instancia de cualquier clase. Pero, como la gente lo utiliza como una forma de atajar la globalización, se lo conoce como programación floja y / o mala.

Por lo tanto, ignoraría global y Singleton ya que ambos no son realmente POO.

Lo que estabas buscando es inyección de dependencia.

Puede consultar información fácil de leer basada en PHP relacionada con la inyección de dependencia (con ejemplos) en http://components.symfony-project.org/dependency-injection/trunk/book/01-Dependency-Injection


7
2017-12-13 00:35



Ambos patrones logran el mismo efecto neto, proporcionando un solo punto de acceso para sus llamadas a la base de datos.

En términos de implementación específica, el singleton tiene una pequeña ventaja de no iniciar una conexión de base de datos hasta que al menos uno de sus otros métodos lo solicite. En la práctica, en la mayoría de las aplicaciones que he escrito, esto no marca una gran diferencia, pero es una ventaja potencial si tienes algunas páginas / rutas de ejecución que no hacen ninguna llamada a la base de datos, ya que esas páginas no alguna vez solicite una conexión a la base de datos.

Otra diferencia menor es que la implementación global puede pisotear involuntariamente otros nombres de variables en la aplicación. Es poco probable que alguna vez declare accidentalmente otra referencia global de $ db, aunque es posible que pueda sobrescribirla accidentalmente (por ejemplo, escriba if ($ db = null) cuando tenga pensado escribir if ($ db == null). El objeto singleton lo impide.


3
2017-09-25 02:44



Si no va a utilizar una conexión persistente, y hay casos en que no lo hace, creo que un singleton es conceptualmente más aceptable que un diseño global en OO.

En una verdadera arquitectura OO, un singleton es más efectivo que crear una nueva instancia del objeto cada vez.


2
2017-09-25 01:03



En el ejemplo dado, no veo ninguna razón para usar singletons. Como regla general, si mi única preocupación es permitir una sola instancia de un objeto, si el idioma lo permite, prefiero usar globales


2
2017-09-25 01:06



En general, usaría un singleton para una conexión de base de datos ... No desea crear una nueva conexión cada vez que necesite interactuar con la base de datos ... Esto podría afectar el rendimiento y el ancho de banda de su red ... ¿Por qué crear un uno nuevo, cuando hay uno disponible ... Solo mis 2 centavos ...

RWendi


1
2017-09-25 01:14



Es bastante simple. Nunca use global O Singleton.


0
2017-09-25 00:59



Como consejo tanto semifallo y global son válidos y se pueden unir dentro del mismo sistema, proyecto, plugin, producto, etc. ... En mi caso, hago productos digitales para web (complemento).

Yo uso solo semifallo en la clase principal y lo uso por principio. Casi no lo uso porque sé que la clase principal no lo instanciará de nuevo

<?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 utilizar para casi todas las clases secundarias, por ejemplo:

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

mientras que en tiempo de ejecución puedo usar Global para llamar a sus métodos y atributos en la misma instancia porque no necesito otra instancia de mi clase de producto principal.

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

Lo que obtengo con Global es usar la misma instancia para poder hacer que el producto funcione porque no necesito una fábrica para instancias de la misma clase, generalmente la fábrica de instancias es para sistemas grandes o para propósitos muy raros.

In conclusion:, debes hacerlo si ya lo entiendes bien, ese es el antipatrón Semifallo y entender el Global, puedes usar una de las 2 opciones o mezclarlas, pero si te recomiendo no abusar ya que hay muchos programadores que son muy excepcionales y fieles a la programación OOP, úsala para clases principales y secundarias que usas mucho dentro de la ejecución hora. (Le ahorra mucha CPU).


0
2018-05-27 18:36