Pregunta

¿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 mejor manera de inicializar la conexión de la base de datos que no sea global o singleton, mencione y describa las ventajas que tiene sobre global o singleton.

¿Fue útil?

Solución

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

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

Conviértalo en un objetivo para mitigar el dolor de hacer cambios en el futuro: un global es peligroso porque es difícil de administrar en un solo lugar. ¿Qué sucede si quiero que el contexto de conexión de la base de datos sea consciente en el futuro? ¿Qué pasa si quiero que se cierre y se vuelva a abrir cada 5 veces que se usó? ¿Qué sucede si decido que, en aras de escalar mi aplicación, quiero usar un grupo de 10 conexiones? ¿O un número configurable de conexiones?

Una fábrica de singleton le brinda esa flexibilidad. Lo configuré con muy poca complejidad adicional y obtengo más que solo acceso a la misma conexión; Obtengo la capacidad de cambiar la forma en que se me pasa esa conexión más adelante de una manera simple.

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

Lo que obtiene una fábrica es por qué obtener conexiones, y un lugar separado para decidir qué conexiones (o conexiones) va a obtener.

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 es súper famosa y se pone dugg y slashdotted y decide que necesita más que una sola conexión, todo lo que tiene que hacer es implementar alguna agrupación en el método getConnection (). O si decide que desea un contenedor que implemente el registro de SQL, puede pasar una subclase de 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, incluidas 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 esto " Característica 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 "codifica para mañana hoy". es siempre algo malo que no me afecta.

Otros consejos

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 fuera 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. Obligando a sus páginas a hacer toda la base de datos conexiones secuencialmente y matando cualquier intento de página asincrónica cargas

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

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

Estoy seguro de que también hay otras posibles consecuencias. 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 este es un sitio web público y desea tráfico, la escalabilidad se convertirá en un problema.

[EDITfont>

En situaciones de mayor escala, crear nuevas conexiones cada vez que golpea 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, se recupera la primera conexión disponible del grupo 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 dos cosas: a) si no se alcanza el número máximo de conexiones permitidas, se abre una nueva conexión, o b) la aplicación se ve obligada a esperar a que una conexión esté disponible .

Nota: en los idiomas .Net, la agrupación de conexiones es manejada por los objetos ADO.Net de manera predeterminada (la cadena de conexión establece toda la información requerida).

Gracias a Crad por comentar sobre esto.

El método singleton se creó para asegurarse de que solo hubiera una instancia de cualquier clase. Pero, debido a que las personas lo usan como una forma de atajar la globalización, se conoce como programación perezosa y / o mala.

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

Lo que estaba buscando es inyección de dependencia .

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

Ambos patrones logran el mismo efecto neto, proporcionando un único 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 hace mucha diferencia, pero es una ventaja potencial si tiene 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 declares accidentalmente otra referencia global de $ db, aunque es posible que puedas sobrescribirla accidentalmente (por ejemplo, escribes if ($ db = null) cuando querías escribir if ($ db == null). El objeto singleton lo impide.

Si no va a utilizar una conexión persistente, y hay casos para no hacerlo, 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.

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

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

RWendi

Es bastante simple. Nunca use global OR Singleton.

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

Solo uso singleton en la clase principal y lo uso por principio. Casi no lo uso porque sé que la clase principal no lo instanciará nuevamente

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

Global para casi todas las clases secundarias, por ejemplo:

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

mientras estoy 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 el 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.

En conclusión: , si ya comprendes bien, ese es el antipatrón Singleton y entiendes el Global , puedes usar una de las 2 opciones o mezclarlas, pero si recomiendo no abusar ya que hay muchos programadores que son muy excepcionales y fieles a la programación orientada a objetos, úsela para las clases principales y secundarias que usa mucho en el tiempo de ejecución. (Te ahorra mucha CPU). ??

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top