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

StackOverflow https://stackoverflow.com/questions/130878

  •  02-07-2019
  •  | 
  •  

Вопрос

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

Код с глобальным

$conn = new PDO(...);

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

Код с помощью 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();
    .
    .
    .
}

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

Это было полезно?

Решение

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

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

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

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

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

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

Пример

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. Максимальное общее количество одновременных подключений, которые может поддерживать ваша база данных, и блокировка доступа новых пользователей к ресурсам.

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

[ПРАВИТЬ]

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

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

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

Спасибо Crad за комментарий по этому поводу.

Метод 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 цента...

РУенди

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

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

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

<?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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top