Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Стоит ли создавать единственный экземпляр класса?
Форумы портала PHP.SU » » Объектно-ориентированное программирование » Стоит ли создавать единственный экземпляр класса?

Страниц (1): [1]
 

1. morph-x - 13 Ноября, 2011 - 14:31:47 - перейти к сообщению
Короче есть у меня класс для работы с БД:
PHP:
скопировать код в буфер обмена
  1. <?PHP
  2.  
  3. class Db {
  4.   private $connection;
  5.    
  6.   public function __construct() {
  7.       // Устанавливаем соединение с БД в переменную $connection
  8.   }
  9.    
  10.   public function query($query) {
  11.       // Выполняем запрос и возвращаем результат
  12.   }
  13. }


Это как бы урезанная версия, но для наглядности сойдет. Суть в том, что соединение с БД у меня будет только одно. Стоит ли создавать единственный экземпляр этого класса? Какой из этих вариантов наиболее правильный?

Вариант 1
PHP:
скопировать код в буфер обмена
  1. <?PHP
  2.   $db = new Db;
  3.   $db->query(/* Здесь запрос */);
  4. ?>


Вариант 2
PHP:
скопировать код в буфер обмена
  1. <?PHP
  2.   Db::query(/* Здесь запрос */);
  3. ?>


Или предложите свой вариант, если эти два считаете неправильными. Заранее спасибо!
2. DeepVarvar - 13 Ноября, 2011 - 14:36:37 - перейти к сообщению
Нужно реализовать синглтон.
Дело не в том какой из вариантов правильный.
Дело в ограничении кол-ва до единственного экземпляра СОЕДИНЕНИЯ а не объекта.
И делается это ограничение со вторым вариантом.
(Добавление)
Конструктор должен быть приватным,
а метод вызова единственного экземпляра публичным.
PHP:
скопировать код в буфер обмена
  1. class db {
  2.  
  3.   protected static $db;
  4.   protected static $link;
  5.  
  6.   public static function getInstance() {
  7.     if (self::$db === null) self::$db = new self();
  8.     return self::$db;
  9.     }
  10.  
  11.   private function __construct() {
  12.     // TODO что-то там у вас
  13.     }
  14.  
  15.   }

(Добавление)
Так вы сможете проверить в методе getInstance (можете назвать его иначе, хоть checkUniqum)
был ли инициализирован ранее данный объект, и если был, вернуть его, в противном случае - инициализировать.
3. morph-x - 13 Ноября, 2011 - 15:04:20 - перейти к сообщению
Я так понимаю, что бы создать экземпляр данного класса нужно сделать так:
PHP:
скопировать код в буфер обмена
  1. <?PHP $db = Db::getInstance(); ?>
4. DeepVarvar - 13 Ноября, 2011 - 15:18:29 - перейти к сообщению
Да.
5. morph-x - 13 Ноября, 2011 - 15:21:00 - перейти к сообщению
DeepVarvar, большое спасибо!
6. White - 13 Ноября, 2011 - 16:26:25 - перейти к сообщению
Существует ли вероятность, что объект вашего класса будет передаваться в качестве аргумента какой либо функции? если нет, тогда какой смысл создавать каждый раз ссылку на единственный объект данного класса, если мы прекрасно можем без него обойтись?
PHP:
скопировать код в буфер обмена
  1. class DB {
  2.   private static $connection;
  3.  
  4.   public static function query() {
  5.     ...
  6.   }
  7. }

класс ведь не реализует никакую бизнес логику вашего приложения, так?
другой вопрос, если вы собираетесь использовать один из шаблонов ORM (TDG, DataMapper, ActiveRecord...). В таком случае данный класс будет наследоваться другими классами, реализующими модели данных вашего приложения, в данной ситуации уже не один, а множество объектов будут реализовывать его методы. Выход в такой ситуации может быть следующим:
PHP:
скопировать код в буфер обмена
  1. class DB {
  2.   private static $connection;
  3.  
  4.   public function __construct() {
  5.     if(!$connection) self::connect();
  6.   }
  7.  
  8.   protected static function connect() {
  9.     ...
  10.   }
  11. }
7. DeepVarvar - 13 Ноября, 2011 - 16:46:45 - перейти к сообщению
White как-то ковырял многолинковый класс. Так не доковырял, да пока и не нужно.
Там никак не мог сделать чтобы методы запросов к базе понимали несколько подключений.
Типа создавал подключение и ссылку на него сохранял
в ассоциативный массив вида: self::$links['linkname'].
Затем вызывал типа так: self::query($qstr,$linkname);
Но что-то работало только с одним соединением, хотя передавал параметр в запрос.
Щас даже найти не могу куски экспериментов.
Если у вас имеется такое решение - раскурите на примере.
8. White - 13 Ноября, 2011 - 17:09:38 - перейти к сообщению
DeepVarvar так я ж предлагаю один линк на всех. линк создается через конструктор, один раз, и хранится как свойство класса. просто если класс должен наследоваться, а в случае с ORM это чаще всего так, синглтоном его уже не сделаешь.
(Добавление)
DeepVarvar а что с многолинковым классом не так?
PHP:
скопировать код в буфер обмена
  1. class DB {
  2.   private static $conn=array();
  3.   private $conn;
  4.  
  5.   public function __construct($dbname) {
  6.     if(!$conn[$dbname]) self::connect($dbname);
  7.     $this->conn = self::$conn[$dbname];
  8.   }
  9.  
  10.   public function query($query) {
  11.     mysqli_query($this->conn, $query);
  12.   }
  13.  
  14.   protected static function connect($dbname) {
  15.     $conn[$dbname] = mysqli_connect();
  16.     mysqli_select_db($conn[$dbname], $dbname);
  17.   }
  18. }


мне кажется так должно вполне нормально работать (только передавать параметры в соединение надо)
9. DeepVarvar - 13 Ноября, 2011 - 17:37:27 - перейти к сообщению
White пишет:
мне кажется
вот и мне казалось. Проверяли?
10. White - 13 Ноября, 2011 - 18:09:57 - перейти к сообщению
DeepVarvar нет, ну если есть сомнения, думаю проверю.
11. Stierus - 14 Ноября, 2011 - 09:12:14 - перейти к сообщению
Как одновременно с двумя базами работать будете, если перейдете на синглтон или статик методы ?
12. caballero - 14 Ноября, 2011 - 10:05:28 - перейти к сообщению
Цитата:
класс ведь не реализует никакую бизнес логику вашего приложения, так?
другой вопрос, если вы собираетесь использовать один из шаблонов ORM (TDG, DataMapper, ActiveRecord...).

смешались в кучу кони люди.
Синглетон служит именно для
1. обеспечения единственного коннекта
2. избегания использования глобальных переменных
3. коннкета "по первому требованию" когда он понадобися а не каждый раз в том числе на тсраницах не требующих конекта с БД.
Актив рекорд и прочее - это другие классы никак не связаные с синглетоном кроме того что там просто используется коннект как в любом другом месте.

Почему то многое стараются упортно свалить в один клас коннект и методы работы с данными БД. Это разная логика для классов.

Цитата:
Как одновременно с двумя базами работать будете, если перейдете на синглтон или статик методы ?

довольно редкая ситуация но ничто не мешает в синглетоне воткнуть еще один коннект
13. Stierus - 14 Ноября, 2011 - 10:17:58 - перейти к сообщению
caballero пишет:
довольно редкая ситуация но ничто не мешает в синглетоне воткнуть еще один коннект

Получится фабричный метод - то, что тут и нужно.

 

Powered by ExBB FM 1.0 RC1