Intereting Posts
Как я могу получить доступ к глубокому объекту, названному как переменная (точечная нотация) в php? Есть ли способ исключить домен из создания ссылок в wordpress Перезапуск изящно / принудительно NodeJS (работает с Forever) из PHP Неужели невозможно написать подсказку пароля php cli, которая скрывает пароль в окнах? Извлечь день / месяц / год с временной отметки на MYSQL присвоение $ _GET и $ _POST одной переменной Доктрина и составные уникальные ключи Как создать файл xlsx без использования какой-либо библиотеки excel PHP Объединение запросов MongoDB с массивом идентификаторов документов как предпочтение сортировки PHP-разбиение на страницы MySQL со случайным упорядочением как подсчитать появление слова в нескольких строках mysql db Правильный способ использования функции «Запомнить меня» в PHP возможно ли получить список определенных пространств имен Автозагрузка классов из разных папок Можно ли использовать curl с относительным путем в PHP?

Существует ли прецедент для одиночных игр с доступом к базе данных в PHP?

Я обращаюсь к своей базе данных MySQL через PDO. Я настраиваю доступ к базе данных, и моя первая попытка заключалась в следующем:

Первое, о чем я думал, – global :

 $db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'root', 'pwd'); function some_function() { global $db; $db->query('...'); } 

Это считается плохой практикой. После небольшого поиска я оказался с шаблоном Синглтона , который

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

Согласно примеру в руководстве, мы должны сделать следующее:

 class Database { private static $instance, $db; private function __construct(){} static function singleton() { if(!isset(self::$instance)) self::$instance = new __CLASS__; return self:$instance; } function get() { if(!isset(self::$db)) self::$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'user', 'pwd') return self::$db; } } function some_function() { $db = Database::singleton(); $db->get()->query('...'); } some_function(); 

Зачем мне этот относительно большой класс, когда я могу это сделать?

 class Database { private static $db; private function __construct(){} static function get() { if(!isset(self::$rand)) self::$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'user', 'pwd'); return self::$db; } } function some_function() { Database::get()->query('...'); } some_function(); 

Этот последний работает отлично, и мне больше не нужно беспокоиться о $db .

Как я могу создать меньший одноэлементный класс, или есть прецедент для одиночных игр, которые мне не хватает в PHP?

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

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

Когда это произойдет, если вы использовали статический класс, вы используете гораздо худший рефакторинг, чем если бы вы использовали синглтон. Синглтон – это шаблон iffy сам по себе, но он довольно легко преобразуется в интеллектуальный заводский шаблон – даже может быть преобразован для использования инъекции зависимостей без особых проблем. Например, если ваш singleton получен через getInstance (), вы можете довольно легко изменить это на getInstance (имя базы данных) и разрешить несколько баз данных – никаких других изменений кода.

Вторая проблема – тестирование (и, честно говоря, это то же самое, что и первая проблема). Иногда вы хотите заменить свою базу данных макетной базой данных. Фактически это второй экземпляр объекта базы данных. Это гораздо сложнее сделать со статическими классами, чем с одноэлементным, вам нужно только измотать метод getInstance (), а не каждый метод в статическом классе (который на некоторых языках может быть очень сложным).

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

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

У синглтонов очень мало – если не сказать «нет» – использование в PHP.

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

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

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

См. Мои слайды для Singletons в PHP. Почему они плохи и как их можно устранить из своих приложений для получения дополнительной информации.

Даже Эрих Гамма , один из изобретателей модели Синглтона, сейчас сомневается в этом шаблоне:

«Я за то, что выбрал Singleton, его использование почти всегда является запахом дизайна»,

дальнейшее чтение

  • Как протестировать шаблон реестра или singleton hard в PHP?
  • Каковы недостатки использования класса базы данных PHP в качестве одноэлементного?
  • Дизайн класса абстракции базы данных с использованием PHP PDO
  • Будет ли синглтон хорошим шаблоном дизайна для сайта микроблогов?
  • Изменение класса для инкапсуляции вместо наследования
  • Как получить доступ к объекту из другого класса?
  • Почему Singletons не используют PHP
  • Переговоры по чистому кодексу – синглы и глобальное государство

Если после вышесказанного вам по-прежнему нужна помощь в принятии решения:

Схема принятия решений по Singleton

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

Чтобы ответить на вопрос, вы правы, что одиночные игры здесь излишни. Простая переменная или функция. Однако лучшим (более надежным) подходом было бы использование инъекции зависимостей для полного устранения глобальных переменных.

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

Больше мыслей. Возможно, вы испытываете случай внедрения шаблонов для шаблонов, и ваша кишка говорит вам «нет, вам не обязательно» по причинам, которые вы указали.

НО: Мы не имеем представления о размере и объеме вашего проекта. Если это простой код, возможно, выбросить, что вряд ли нужно будет изменить, тогда да, идите и используйте статические члены. Но если вы считаете, что вашему проекту может потребоваться масштабирование или подготовка к кодированию обслуживания вниз по дороге, то да, вы можете использовать шаблон Singleton.

Во-первых, я просто хочу сказать, что я не очень много использую шаблон Singleton. Зачем нужно, чтобы один объект полностью обрабатывал все приложение? Специально для баз данных, что делать, если я хочу подключиться к другому серверу базы данных? Я должен каждый раз отключать и снова подключаться …? Так или иначе…

Есть несколько недостатков в использовании глобальных приложений в приложении (что традиционное использование шаблона Singleton):

  • Трудно провести единичный тест
  • Проблемы с инъекцией зависимостей
  • Может создавать проблемы с блокировкой (многопоточное приложение)

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

Вы можете ограничить количество экземпляров, которые может иметь класс, не используя традиционный метод getInstance :

 class Single { static private $_instance = false; public function __construct() { if (self::$_instance) throw new RuntimeException('An instance of '.__CLASS__.' already exists'); self::$_instance = true; } private function __clone() { throw new RuntimeException('Cannot clone a singleton class'); } public function __destruct() { self::$_instance = false; } } $a = new Single; $b = new Single; // error $b = clone($a); // error unset($a); $b = new Single; // works с class Single { static private $_instance = false; public function __construct() { if (self::$_instance) throw new RuntimeException('An instance of '.__CLASS__.' already exists'); self::$_instance = true; } private function __clone() { throw new RuntimeException('Cannot clone a singleton class'); } public function __destruct() { self::$_instance = false; } } $a = new Single; $b = new Single; // error $b = clone($a); // error unset($a); $b = new Single; // works 

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

Подумайте, как ваше решение отличается от того, которое представлено в документах PHP. Фактически, существует только одна «маленькая» разница: ваше решение предоставляет вызывающим абонентам получателя с экземпляром PDO , в то время как в документах содержатся вызовы Database::singleton с экземпляром Database (они затем используют getter для этого получить экземпляр PDO ).

Итак, какой вывод мы достигли?

  • В коде документации получатели получают экземпляр Database . Класс Database может выставлять (на самом деле, он должен разоблачить, если вы перейдете ко всем этим проблемам) более богатый или более высокий уровень интерфейса, чем объект PDO он обертывает.
  • Если вы измените свою реализацию, чтобы вернуть другой (более богатый) тип, чем PDO , то две реализации эквивалентны. Нет никакой выгоды от выполнения ручной версии.

С практической стороны, Синглтон – довольно спорный образец. Это происходит главным образом потому, что:

  • Это злоупотребление. Новичкам программистам громать Синглтон намного легче, чем они замаскивают другие шаблоны. Затем они продолжают применять свои новообретенные знания повсюду, даже если проблема под рукой может быть решена лучше без Синглтона (когда вы держите молоток, все выглядит как гвоздь).
  • В зависимости от языка программирования внедрение Singleton в герметичном, негерметичном режиме может оказаться титанической задачей (особенно, если у нас есть расширенные сценарии: синглтон в зависимости от другого синглтона, синглтонов, которые можно уничтожить и воссоздать, и т. Д. ). Просто попробуйте найти «окончательную» реализацию Синглтона на C ++, я смею вас (я владею новаторским Modern C ++ Design Andrei Alexandrescu, который документирует большую часть беспорядка).
  • Он накладывает дополнительную рабочую нагрузку как при кодировании Singleton, так и при написании кода для доступа к ней, рабочей нагрузки, которой вы можете обойтись, не следуя нескольким ограничениям на себя, которые вы пытаетесь сделать с вашими программными переменными.

Итак, как окончательный вывод: ваш синглтон в порядке. Не использовать Singleton вообще просто отлично в большинстве случаев.

Ваша интерпретация верна. Синглтоны имеют свое место, но злоупотребляют. Часто доступ к статическим функциям-членам достаточно (особенно, когда вам не нужно каким-либо образом контролировать время создания). Лучше, вы можете просто поместить некоторые свободные функции и переменные в пространство имен.

При программировании нет «правильных» и «неправильных»; есть «хорошая практика» и «плохая практика».

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

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

не всегда плохая практика иметь глобальные объекты. Если вы знаете, что собираетесь использовать его глобально / везде / все время, это может быть одно из немногих исключений. Однако глобалы обычно считаются «плохой практикой» таким же образом, что goto считается плохой практикой.

Я не вижу в этом никакого смысла. Если вы внедрили класс таким образом, чтобы строка соединения была взята в качестве параметра конструктору и поддерживала список объектов PDO (по одному для каждой уникальной строки соединения), то, возможно, была бы какая-то польза, но реализация singleton в этот случай кажется бессмысленным.

Насколько мне известно, вы ничего не пропустили. Пример довольно ошибочен. Это будет иметь значение, если в классе singleton были некоторые нестатические переменные экземпляра.