ссылка на объект при создании. как? :)

_vampiro_

Новичок
ссылка на объект при создании. как? :)

Взял тут стрый свой сайт и переделываю под пхп5 (объекты)

Убрал все функции работы с БД и наваял "модный" объект. Теперь такая чтука:
Раньше везде у меня были прописаны просто вызовы функций. (например, mysql_query() ).
теперь вместо этого я прописываю "$a=new db; $a->query();"

а теперь вопрос... как бы мне не создавать объект каждый раз новый, а сделать так, чтобы при создании, мне отдавалась ссылка на уже существующий.

Пока что наваял вот такое:
PHP:
public function GetInstance(){
  foreach ($GLOBALS as $i)
    if ($i instanceof db) $instance=$i;
  if (!$instance) {/* тут создаем объект с глобальным именем*/}
 return $instance;
}
А можно как-то это же "впихнуть" в "__construct"? :) или пните меня в нужную сторону, если я не так делаю... принципиально. (оставить функции не предлагать:) )
 

_vampiro_

Новичок
PHP:
class news extends simple_part{

  function add ($text){
    $a = db::GetInstance();
    $a->query("insert into ....");

  }
}
есть предложения как "не создавать" переменную $a?
 

Scud

Новичок
Код:
class DB
{
     private function __construct() {}
     public static function instance()
     {
             static $instance = null;
             if (is_null($instance)) {
                    $instance = new DB();
             }
             return $instance;
     }
}
$db = DB::instance();
$db->doSomeThing();

А вообще Singleton
 

vasa_c

Новичок
PHP:
$a=new db; $a->query();
Как понимаю db здесь символизирует базу данных.
База данных существует одна для всего сценария. Таким образом и объект по сути д.б. одним.
А так он создается для каждого запроса.

Может быть при переходе на ООП не только синтаксис поменять, но и над идеологией подумать?
 

_vampiro_

Новичок
покурил поиск. Полез пробовать. :) Знал, что все до меня уже изобретено... (ёптыть, я как-то через анус все сделал снова)

Вызывать через $a=new DB; нельзя, я правильно понял? Только через ::instance()?

-~{}~ 08.06.06 18:09:

vasa_c
я как раз и думаю как бы не создавать... просто создав
$Datbase=new DB;
в самом начале, я не могу получить к $Database доступ из объектов кроме как через глобалс. а не хочется привязывать к определенной переменной. Синглтон то, что надо... вроде:)

-~{}~ 08.06.06 18:43:

Переписал, все тесты отработали. Спасибки! :)

-~{}~ 09.06.06 16:44:

Заюзал Singleton;

теперь class db можно создать 1 раз.

теперь такой вопрос, мне для адаптации всего сайта надо будет прописывать в каждом методе (где используется запрос)
PHP:
$datalink = db::Instance();
$datalink->Query(...);
?
нет более простого пути?
 

whirlwind

TDD infected, paranoid
>теперь такой вопрос, мне для адаптации всего сайта надо будет прописывать в каждом методе (где используется запрос)

Смотря что там было. Вообще хорошим решением внутри объектов, использующих коннект было бы определить метод getConnection. Это позволить тестировать класс на основе абстрактного драйвера и дальнейший рефакторинг не отягощяется переписыванием

>мне для адаптации всего сайта надо будет прописывать в каждом методе

А уже в getConnection как угодно, хоть сингельтон хоть через фабрику. Не стоит злоупотреблять статическими вызовами, так как в плане рефакторинга они фактически ничем не отличаются от того же самого вызова функций my_sql*
 

_vampiro_

Новичок
zerkms
unreal. А как же Рефакторинг? :)

whirlwind
Понял... будем добавлять методы в родителя. Про "Фабрику" видел один раз где-то мельком, но не нашел где читануть. Тут в Избранном линьк умер. :) Буду вас донимать.

Всем Спасибо... ушел ковырять :)
 

whirlwind

TDD infected, paranoid
На вашем этапе вам все равно фабрика это или сингельтон. В некоторых случаях может понадобиться коннект к нескольким источникам или в зависимости от условий выбирать конкретную БД. Тогда в getConnection меняем обращение к сингельтону db (который становится фабрикой) например так

PHP:
function getConnection(){
      return DB::getConnection($this->getDSN());
}
при этом прототип
PHP:
DB::getConnection($dsn='default')
ничуть не будет противоречить старому коду
PHP:
function getConnection(){
    return DB::getConnection();
}
а код, где у вас выполняются непосредственно запросы вообще не потребует изменений.
 

_vampiro_

Новичок
zerkms
сайт работающий. И хочется производить лишь структурные изменения. :) Чтобы сохранять функциональность.

-------------------------

А что если
PHP:
pritected $dbConnection = Null;
, в Конструктор засунуть
PHP:
$this->DbConnection =  $this->GetConnection();
и в коде уже использовать
PHP:
$this->DbConnection->Query(...);
 

whirlwind

TDD infected, paranoid
Если у вас столько запросов, что $this->getConnection() приведет к заметной потере производительности, то вам отнюдь не код рефакторить надо :)

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

Gorynych

Посетитель PHP-Клуба
шоблон класса-одиночки (singleton) дело хорошее, но проблема в том, что иногда не очень хочется определять в другом классе переменную, ответственную за объект доступа к данным.

лично я для этого использую такую функцию, основанную на поведении статических переменных в PHP 5:
Код:
dataobj.php
========

class DataObj {
    ...
}

function getDBLink() {
    static $db = null;

    // если линк на объект не инициализирован - создать объект
    if ( !isset($db) ) {
        $db = new DataObj();
    }
    return $db;
}

...

какой-то другой файл или класс:
========================

// ну и далее используем по мере надобности:


class A {
   ...

   public function GetSomething(...) {
       $db = getDBLink();

        ...
    }
}
 

_vampiro_

Новичок
не, производительность не упадет - объект один, соединение есть. Вызывать можно сколь угодно. Тут вопрос именно в коде.


Если в каждом методе использовать свою переменную (локальную) и её объявлять - то надо будет полазать по коду (пусть и поиском) и прописать.

Если делать через $this->$db->метод, то, поскольку у меня методы совпадают с теми функциями, что были написаны ранее, я просто пущу замену строки во всех файлах папки. + потом пропишу у родителя метод и инициализацию в конструкторе.

Меня смущает...->...-> (); некрасиво как-то.
 

zerkms

TDD infected
Команда форума
сайт работающий. И хочется производить лишь структурные изменения.
повторюсь - для того чтобы рефакторить код, он [код] должен быть соответствующего качества.
русская поговорка: из г**на конфетку не сделаешь (извините за мой латиноамериканский (с))
 
Сверху