Глобальный или Синглтон для подключения к базе данных?


в чем преимущество использования синглтона вместо глобального для соединений с базой данных в PHP? Я чувствую, что использование синглтона вместо глобального делает код излишне сложным.

код с глобальными

$conn = new PDO(...);

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

код с одноплодной

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

Если есть лучший способ инициализации подключения к базе данных, кроме глобального или одноэлементного, пожалуйста, укажите его и опишите преимущества, которые он имеет по сравнению с глобальным или одноэлементным.

9 76

9 ответов:

Я знаю, что это старый, но ответ Dr8k был почти там.

когда вы рассматриваете возможность написания фрагмента кода, предположим, что он изменится. Это не означает, что вы предполагаете, какие изменения он будет поднимать на него в какой-то момент в будущем, а скорее, что какая-то форма изменения будет сделана.

сделайте это целью смягчить боль от внесения изменений в будущем: глобальный опасно, потому что трудно управлять в одном месте. Что делать, если я хочу сделать этот контекст подключения к базе данных в будущем? Что делать, если я хочу, чтобы он закрывался и снова открывался каждый 5-й раз, когда он использовался. Что если я решу, что в интересах расширения моего приложения я хочу использовать пул из 10 подключений? Или настраиваемое количество соединений?

A singleton factory дает вам эту гибкость. Я настраиваю его с очень небольшой дополнительной сложностью и получаю больше, чем просто доступ к одному и тому же соединению; я получаю возможность измените, как это соединение передается мне позже простым способом.

обратите внимание, что я говорю singleton factory а не просто синглтон. Правда, между синглтоном и Глобалом очень мало разницы. И из-за этого нет причин иметь одноэлементное соединение: зачем вам тратить время на настройку, когда вместо этого вы можете создать обычный глобальный?

то, что завод получает вас это почему, чтобы получить соединения, и отдельное место, чтобы решить, какие соединения (или соединение) вы собираетесь получить.

пример

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

затем, через 6 месяцев, когда ваше приложение станет супер известным и получит dugg и slashdotted, и вы решите, что вам нужно больше, чем одно соединение, все, что вам нужно сделать, это реализовать некоторый пул в методе getConnection (). Или если вы решите, что вам нужна оболочка, которая реализует ведение журнала SQL, вы можете передать подкласс PDO. Или если вы решите, что хотите установить новое соединение каждый вызов, вы можете сделать это. Он гибкий, а не жесткий.

16 строк кода, включая фигурные скобки, которые сэкономят вам часы и часы рефакторинга до чего-то жутко похожего вниз по строке.

обратите внимание, что я не рассматриваю эту "функцию ползучести", потому что я не делаю никакой реализации функций в первом раунде. Это пограничная линия "будущая ползучесть", но в какой-то момент идея о том, что" кодирование на завтра сегодня " - это всегда плохо для меня это не джайв.

Я не уверен, что могу ответить на ваш конкретный вопрос, но хотел бы предложить, что объекты глобального / одноэлементного соединения могут быть не лучшей идеей, если это для веб-системы. СУБД, как правило, предназначены для эффективного управления большим количеством уникальных соединений. Если вы используете объект глобального соединения, то вы делаете несколько вещей:

  1. заставляя вас страницы делать все базы данных соединения последовательно и убийство любые попытки асинхронная страница нагрузки.

  2. потенциально удерживая открытые замки элементы базы данных длиннее, чем необходимо, замедление в целом производительность базы данных.

  3. максимизировать общее количество одновременное подключение вашего база данных может поддерживать и блокировать новые пользователи от доступа к ресурсы.

Я уверен, что есть и другие потенциальные последствия. Помните, что этот метод будет пытаться поддерживать базу данных подключение для каждого пользователя, заходящего на сайт. Если у вас есть только один или два пользователя, не проблема. Если это общедоступный веб-сайт, и вы хотите трафик, то масштабируемость станет проблемой.

[EDIT]

в более масштабированных ситуациях создание новых соединений каждый раз, когда вы попадаете в базу данных, может быть плохим. Однако ответ заключается не в том, чтобы создать глобальное соединение и повторно использовать его для всего. Ответ-пул соединений.

с подключением объединение в пул, поддерживается ряд различных соединений. Когда приложение требует подключения, первое доступное подключение из пула извлекается, а затем возвращается в пул, как только его работа будет выполнена. Если соединение запрашивается, и ни одно из них не доступно, произойдет одно из двух: а) если максимальное количество разрешенных соединений не достигнуто, открывается новое соединение или б) приложение вынуждено ждать, пока соединение станет доступный.

Примечание: в языках .Net пул соединений обрабатывается ADO.Net объекты по умолчанию (строка подключения задает всю необходимую информацию).

спасибо Крэд для комментирования этой.

метод singleton был создан, чтобы убедиться, что существует только один экземпляр любого класса. Но, поскольку люди используют его как способ быстрой глобализации, он становится известным как ленивое и / или плохое Программирование.

поэтому я бы проигнорировал global и Singleton, поскольку оба они на самом деле не ООП.

то, что вы ищете-это инъекции зависимостей.

вы можете проверить на легко читаемой PHP на основе информации, связанной с инъекцией зависимостей (с примеры) на http://components.symfony-project.org/dependency-injection/trunk/book/01-Dependency-Injection

оба шаблона достигают одного и того же чистого эффекта, обеспечивая одну точку доступа для вызовов базы данных.

с точки зрения конкретной реализации, синглтон имеет небольшое преимущество не инициировать подключение к базе данных, пока по крайней мере один из ваших других методов не запросит его. На практике в большинстве приложений, которые я написал, это не имеет большого значения, но это потенциальное преимущество, если у вас есть несколько страниц / путей выполнения, которые не вызывают никаких вызовов базы данных все, так как эти страницы никогда не будут запрашивать подключение к базе данных.

еще одно незначительное различие заключается в том, что глобальная реализация может непреднамеренно топтать другие имена переменных в приложении. Маловероятно, что вы когда-нибудь случайно объявите другую глобальную ссылку $db, хотя возможно, что вы можете перезаписать ее случайно ( скажем, вы пишете if($db = null), когда вы хотели написать if($db == null). Одноэлементный объект предотвращает это.

Если вы не собираетесь использовать постоянное соединение, и есть случаи, когда этого не делается, я считаю, что синглтон концептуально более приемлемый, чем глобальный в дизайне OO.

в истинной архитектуре OO синглтон более эффективен, чем создание нового экземпляра объекта каждый раз.

на данном примере я не вижу причин использовать синглеты. Как правило, если моя единственная забота-разрешить один экземпляр объекта, если язык позволяет это, я предпочитаю использовать глобалы

В общем случае я бы использовал синглтон для подключения к базе данных... Вы не хотите создавать новое соединение каждый раз, когда вам нужно взаимодействовать с базой данных... Это может повредить производительности и пропускной способности сети... Зачем создавать новый, когда есть один доступный... Просто мои 2 цента...

RWendi

Это довольно просто. Никогда не используйте global или Singleton.

как советы как синглтон и глобальные действительны и могут быть соединены в пределах одного и того же система, проект, плагин, продукт и т. д ... В моем случае, я делаю цифровые продукты для web (плагин).

Я использую только синглтон в основном классе, и я использую его по принципу. Я почти не использую его, потому что знаю, что основной класс не будет создавать его снова

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

глобальные польза для почти всего средние классы, например:

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

во время выполнения я могу использовать глобальные чтобы вызвать их методы и атрибуты в том же экземпляре, потому что мне не нужен другой экземпляр моего основного класса продукта.

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

Я получаю с глобальным, чтобы использовать один и тот же экземпляр, чтобы иметь возможность заставить продукт работать, потому что мне не нужна фабрика для экземпляров одного и того же класса, обычно фабрика экземпляров предназначена для больших систем или для очень редких цели.

In conclusion:, вы должны, если вы уже хорошо понимаете, что это анти-шаблон Синглтон и понять глобальные, вы можете использовать один из двух вариантов или смешать их, но если я рекомендую не злоупотреблять, так как есть много программистов, которые очень исключение и верны программированию ООП, используйте его для основных и средних классов, которые вы используете много в течение времени выполнения. (Это экономит вам много процессора).