объекты и библиотеки

HraKK

Мудак
Команда форума
У меня сделано так.
Есть класс User при создании которого агрегируется обьект UserModel. В обьете UserModel получаем синглетон DataBase.
 

Pigmeich

Новичок
quad_4
Ну это и есть шаманить. Особенно если библиотеки не твои, а чужие.

а смысл синглтона в том, что не надо тащить за собой на протяжении всего скрипта глобальную переменную (ссылку на объект или connection resource).
Смысл немного в другом - в C++ преодолевается разделение глобальных переменных модулей.
И тащить ссылку тебе всё равно придётся - в виде класса синглтона.

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

Pigmeich

Новичок
HraKK
Тебе часто приходилось выносить подключение к базе в глобальные переменные?
 

quad_4

Новичок
Автор оригинала: Pigmeich
И тащить ссылку тебе всё равно придётся - в виде класса синглтона.
да не придётся, в любом месте я вызову class::instance() и получу ссылку на объект

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

HraKK

Мудак
Команда форума
Pigmeich
Не часто, потому что есть синлетон.
 

Arekus

Новичок
Автор оригинала: Pigmeich
Ещё раз, в большинстве мест достаточно создать подключение, сделать запрос, получить результат и закрыть подключение. И, обычно, это умещается в одну функцию.
Ога. А потом когда приходится заниматься поддержкой подобных проектов начинаешь ловить непонятки - чего откуда взялось/где глюки происходят/где тормоза скрипт ловит.
С синглтоном - отличный подход. Еще к нему можно добавить класс обертки (паттерн адаптер) и проводить запросы через него. Ну и добавив обертке возможность вывода инфы (например, по параметру) о том, откуда пришел запрос, сколько времени он выполнялся, explain и т.п.
В случае подключения к нескольким базам: обертка работает с несколькими синглтонами подключений перенаправляя запрос либо по параметру, либо по распознаванию таблиц-полей в запросе. Т.е. для вышестоящего кода становится абсолютно фиолетово - куда происходит обращение.
 

Alexandre

PHPПенсионер
В случае подключения к нескольким базам: обертка работает с несколькими синглтонами подключений
В случае работы с несколькими подключениями - надо делать фабрику. Фабрика вызывает класс-адаптер и реализует Interface IDB. Данный класс вызывает в зависимости от типа БД, соответствующий класс MySQLDB или MySQLi или PgSQL, в зависимости от необходимости.
А в конкретном коде это выглядит так
PHP:
$fdb = new FactoryDB;
$cnn1= $fdb->Create( 'MySQL', 'cnn params' );
$cnn2 = $fdb->Create( 'PgSQL', 'cnn params' );
... [ any class]
$db = FactoryDB::getInstance();
$db->Query( $sql1, $cnn1 ); $res1= $db->FetchObject($cnn1); // первый рекордсет
$db->Query( $sql2, $cnn2 ); $res2= $db->FetchObject($cnn2); // второй рекордсет
По умолчанию используется одно подключение (нолевое), указывать параметр "номер подключения" не надо.

Именно в этом случае и используется реализация Interface IDB, так как написано только два модуля-адаптера (класса оберток) для подключения БД. Если кто-то захочет дописать свой модуль, например MsSQL,то он должен реализовать все методы класса обертки.
 

Pigmeich

Новичок
Arekus
Обертки - рулят всегда, не спорю.

Вопрос про "нафига синглтон".
quad_4
Зачем закрывать подключение, если оно persistent? В большинстве реализаций либ, персистенты идут через пул подключений, что может привести даже к ускорению подключения при нескольких concurent скриптах.

Alexandre
Фактически, фабрика и абстрактный интерфейс реализованны в PDO. Как к ни относишься?
 

Arekus

Новичок
Автор оригинала: Alexandre
В случае работы с несколькими подключениями - надо делать фабрику.
Немного другое имел ввиду. Извиняюсь за много строк, но пример рабочий и четко передает суть.
PHP:
<?php
class MultiDBInterface
{
  public static function query($sql, $cnn = 'con1')
  {
    global $multi_db_obj;
    $multi_db_obj->query($sql, $cnn);
  }
}

class MultiDB
{
  private $connections;
  private $info = array('con1' => 'DbFirst', 'con2' => 'DbSecond');
  
  public function query($sql, $cnn)
  {
    if (empty($this->connections[$cnn])) $this->openConnect($cnn);
    $this->connections[$cnn]->doQuery($sql);
  }
  
  private function openConnect($cnn)
  {
    eval('$this->connections[$cnn] = ' . $this->info[$cnn] . '::create();');
  }
}

class DbFirst
{
  private function __construct()
  {
    // собственно открываем соединение
  }
  
  public static function create()
  {
    return new DbFirst();
  }
  
  public function doQuery($sql)
  {
    echo '<br> ' . $sql;
  }
}

class DbSecond
{
  private function __construct()
  {
    // собственно открываем соединение
  }
  
  public static function create()
  {
    return new DbSecond();
  }
    
  public function doQuery($sql)
  {
    echo '<br> ' . strtoupper($sql);
  }
}

$multi_db_obj = new MultiDB();
$multi_db_obj->query('qwe', 'con2');

class INeedSomeDibies
{
  public function need()
  {
    MultiDBInterface::query('qweqweqweqweqwe');
  }
}

$q = new INeedSomeDibies();
$q->need();
?>
ну и бонусы такого подхода: минимум объектов в глобальной видимости, не надо таскать через глобалы ссылки на объекты подключений.
И есть еще способы улучшить этот код (например, идентификаторы подключений - в константы)
 

dark-demon

d(^-^)b
> минимум объектов в глобальной видимости

класс - это глобальный объект


> не надо таскать через глобалы ссылки на объекты подключений

global $db1; // получаем объект для работы с бд

$db= DB1::getInstance(); // идиотский способ сделать то же самое

$db= new DB1; // короче, но не менее бессмысленно
 

cDLEON

Онанист РНРСlub
Pigmeich
Почему нет ?
Мне например удобнее сделать так:
PHP:
DB::connect($dbHost,$dbUser,$dbPass,$dbName,"connection_name");
DB::connect($dbHost,$dbUser,$dbPass,$dbName,"connection_name2");
//Если требуется коннект, который делается первым, либо выставленный по-дефолту
DB::query("SELECT blablabla...");
//если требуется ко второму
DB::query("SELECT blablabla...","connection_name2");
Вы всё ещё щитаете, что лучше тоскать глобал?
 

korchasa

LIMB infected
$GLOBALS:
+ простая реализация
+ отсутствие статической зависимости
+ легкость модификации значения
- отсутствие контроля над модификациями (хрен найдешь место, где кто-то изменил содержимое переменной)
- возможный конфликт с локальными переменными
Singleton:
+ простая реализация
+ легкость модификации значения
+ контроль над модификациями (только через setInstance, например)
- статическая привязка к классу

Кроме них можно использовать Registry (см. Zend_Registry), умные ObjectLocator'ы, IoC контейнеры и прочие сборщики, просто хранители "нужных" объектов:

PHP:
class Context {
  function getDbConn()
  {
    return $this->db_conn;
  }
  function setDbConn($value)
  {
    $this->db_conn = $value;
  }
}
PS: http://wiki.agiledev.ru/doku.php?id=ooad:manage_dependencies_in_php_code
 

Pigmeich

Новичок
cDLEON
Я считаю, что лучше коннектиться на месте персистентом через PDO.

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

HraKK

Мудак
Команда форума
Pigmeich
Персистан конект часто бывает злом.

Синглетон позволяет мне быть увереным что у меня _именно_ то подключение которое я определил заранее.
 

korchasa

LIMB infected
Автор оригинала: Pigmeich
cDLEON
Я считаю, что лучше коннектиться на месте персистентом через PDO.
Только если количество одновременных запросов меньше лимита ;)

Но если кому неймется держать где-то в глобальной области коннект (неважно в каком виде), то зачем именно синглетон непонятно. (Хотя вы можете просмотреть на верх и найти в моем посте как бы ответ на этот вопрос).
Потому что хочется быть уверенным, что он ОДИН.
 

iceman

говнокодер
кажется про меня вообще забыли

-~{}~ 02.11.07 14:18:

korchasa

очень занимательная ссылка... вот там почти все ответы на мои вопросы!
 

Alexandre

PHPПенсионер
Фактически, фабрика и абстрактный интерфейс реализованны в PDO. Как к ни относишься?
К PDO отношусь Положительно. Но все равно приходится писать собственные обертки, если работаешь на публику, PDO может быть не везде установленно.

-~{}~ 02.11.07 15:38:

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

-~{}~ 02.11.07 15:39:

использование eval - тоже не рекомендуется
 
Сверху