ФорумПрограммированиеPHP для идиотов → Синглтон и жуткие извращения

Синглтон и жуткие извращения

  • StGeass

    Сообщения: ? Репутация: N Группа: Кто попало

    Spritz 24 декабря 2011 г. 10:49

    В общем сабж страшный боян и состоит в следующем, есть банальный класс работы с БД:

    $db =& new db();


    Все прекрасно и замечательно, но меня корежит то что каждому классу, которому необходима работа с БД, приходится передавать ссылку на экземпляр класса скажем так:


    private function __construct(&db) {
    $this->db =& $db;
    }


    В общем удобства это не доставляло, зависимость кода только повышалась и вообще полная печаль.

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

    Дальше на ум конечно же приходит пресловутый паттерн Singlton который отчасти решал задачу позволяя делать запросы вида:

    dh::getInstance()->getRow();
    //OR
    dh::instance->getRow();


    Но тут меня понесло и я желая получить то что хотел родил это:

    class db {
    public $test_row = 'Work!';
    public static $instance;

    function __construct() { }

    public static function __callStatic($name, $arguments) {
    if(!self::$instance) self::getInstance();

    $methodname = preg_replace('/\_?/', '', $name);

    self::$instance->$methodname($arguments);
    }

    public static function getInstance() {
    self::$instance = new db();

    return self::$instance;
    }

    public function getRow () {
    return $this->test_row;
    }
    }

    echo db::_getRow(); //Выведет 'Work!'


    В общем получилось то что хотел, к методам можно обращаться либо через экземпляр класса, либо как к статическим (через '_'), при этом не теряя указателя $this. Но все это изрядно попахивает и отнюдь не цветочками.

    Собственно вопрос:
    Есть у кого то адекватная реализация, балансирующая между удобством и здравым смыслом?
  • Ivan

    Сообщения: ? Репутация: N Группа: Адекваты

    Spritz 24 декабря 2011 г. 11:12, спустя 23 минуты 29 секунд

    $db =& new db();

    Сам то понял что написал?
  • StGeass

    Сообщения: ? Репутация: N Группа: Кто попало

    Spritz 24 декабря 2011 г. 11:15, спустя 2 минуты 35 секунд


    $db =& new db();

    Сам то понял что написал?


    А что там не так?

    P.S. Код естественно далек от реального и намеренно минимизирован для более простого понимания.
  • Абырвалг

    Сообщения: 6477 Репутация: N Группа: Джедаи

    Spritz 24 декабря 2011 г. 11:20, спустя 5 минут 29 секунд

    так писали во времена пхп4
  • Frozzeg

    Сообщения: 5642 Репутация: N Группа: Джедаи

    Spritz 24 декабря 2011 г. 11:22, спустя 1 минуту 44 секунды

    Сам то понял что написал?

    ну а че, вполне логично, получить ссылку вместо самого объекта
    You can be anything you want to be. Just turn yourself into anything you think that you could ever be.
  • StGeass

    Сообщения: ? Репутация: N Группа: Кто попало

    Spritz 24 декабря 2011 г. 11:27, спустя 4 минуты 55 секунд


    так писали во времена пхп4

    Ну первой попавшей мне в руки литературой была книга по php4, так что не исключаю наличие пары не существенных атавизмов, главное что бы не были критичными
  • Ivan

    Сообщения: ? Репутация: N Группа: Адекваты

    Spritz 24 декабря 2011 г. 11:36, спустя 9 минут 28 секунд


    Сам то понял что написал?

    ну а че, вполне логично, получить ссылку вместо самого объекта


    Так это одно и то же получится
  • master

    Сообщения: 3236 Репутация: N Группа: Джедаи

    Spritz 24 декабря 2011 г. 12:56, спустя 1 час 19 минут 54 секунды

    Так это одно и то же получится

    в пхп4 - нет )
    не всё полезно, что в swap полезло
  • Tekuto

    Сообщения: ? Репутация: N Группа: Адекваты

    Spritz 24 декабря 2011 г. 13:01, спустя 4 минуты 51 секунду

    Пых 4-ый разве актуален??? Сегодня, когда готовится уже 6-ой???
  • phpdude

    Сообщения: 26617 Репутация: N Группа: в ухо

    Spritz 24 декабря 2011 г. 13:16, спустя 15 минут 1 секунду


    Пых 4-ый разве актуален??? Сегодня, когда готовится уже 6-ой???
    ДА КОНЕЧНО БЛЯДЬ
    Сапожник без сапог
  • master

    Сообщения: 3236 Репутация: N Группа: Джедаи

    Spritz 24 декабря 2011 г. 14:21, спустя 1 час 5 минут 2 секунды

    В общем получилось то что хотел, к методам можно обращаться либо через экземпляр класса, либо как к статическим (через '_'), при этом не теряя указателя $this. Но все это изрядно попахивает и отнюдь не цветочками.

    Правильно, с этим говнищем поймаешь только баги.

    Есть у кого то адекватная реализация, балансирующая между удобством и здравым смыслом?

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


    class ControllerPrototype{
     function __get($name){
       if (preg_match('#^[A-Z]', $name)){
         $this->$name = new $name;
       } else {
         // ошибка, нет такого поля
       }
     }
    }

    function ModelPrototype(){
     protected $db_instance;
     protected $db_alias;
     protected $table_name;
     
     function __construct(){
       $this->db_instance = Factory::getDB($this->db_alias);
       // находим экземпляр класса базы данных по его алиасу. алиасов может быть несколько, по количеству баз, обычно он один т.к. база одна, но может быть сколько угодно
       // обращаемся к фабрике, можно использовать статический вызов или какой-то другой способ.
     }

     function direct_query($query_str){
       return $this->db_instance->query($query_str);
     }

     function item($id){
       $this->db_instance->query("SELECT * FROM {$this->table_name} where `id`=?", $id);
       return $this->db_instance->fetch_result();
     }

     // любые другие функции для работы с данными - выборки, удаления и т.д.
    }


    // Опишем модель для работы с пользователями
    class Users extends ModelPrototype{
     protected  $db_alias = 'db1';
     protected $table_name = 'users';
    }

    class FooController extends Controller {
     function my_action(){
       $user = $this->Users->item(7); // получаем юзера с id=7
       var_dump ($user);
     }
    }


    запросы к БД и создание экземпляра БД показаны схематично, главное здесь - вызов модели
    $this->Users
    экземпляр модели создаётся в момент первого к ней обращения. естественно, поле $this->Users не должно быть инициализировано
    считаем что за один запуск скрипта вызывается только один контроллер. если будет использоваться несколько контроллеров - то потребуется какой-то глобальный массив для хранения загруженных моделей


    class ControllerPrototype{
    function __get($name){
    if (preg_match('#^[A-Z]', $name)){
    $this->$name = Factory::getModel($name);
    } else {
    // ошибка, нет такого поля
    }
    }
    }


    моар примеров тут:
    http://pyha.ru/forum/topic/7079.msg161461#msg161461
    http://pyha.ru/forum/topic/6255.msg142119#msg142119
    не всё полезно, что в swap полезло
  • Tekuto

    Сообщения: ? Репутация: N Группа: Адекваты

    Spritz 24 декабря 2011 г. 14:07, спустя 23 часа 45 минут 30 секунд

    ДА КОНЕЧНО БЛЯДЬ

    Почему актуален?
  • phpdude

    Сообщения: 26617 Репутация: N Группа: в ухо

    Spritz 24 декабря 2011 г. 14:11, спустя 4 минуты 23 секунды

    Tekuto, ВОПРОСЫ ЗАДАВАТЬ БУДЕШЬ В АРМИИ
    Сапожник без сапог
  • Tekuto

    Сообщения: ? Репутация: N Группа: Адекваты

    Spritz 24 декабря 2011 г. 14:34, спустя 22 минуты 51 секунду

    РЯДОВОЙ ЗАПАСА (2 РА 999000А) {+++115+++} даже так

    РЯДОВОЙ ЗАПАСА
    2 РА
    999000А

    поэт блеать
  • phpdude

    Сообщения: 26617 Репутация: N Группа: в ухо

    Spritz 24 декабря 2011 г. 14:34, спустя 31 секунду


    РЯДОВОЙ ЗАПАСА (2 РА 999000А) {+++115+++} даже так

    РЯДОВОЙ ЗАПАСА
    2 РА
    999000А

    поэт блеать
    А НОМЕРОК ТО КУПИЛ БЛЕЯДЬ СТОПУДОВО! ПОД ТРИПУНАЛ ТЕПЯ НАДО ПЛЕЯТЬ!
    Сапожник без сапог

Пожалуйста, авторизуйтесь, чтобы написать комментарий!