За последние 24 часа нас посетил 59631 программист и 1851 робот. Сейчас ищут 1886 программистов ...

Как передавать ресурс базы в ООП?

Тема в разделе "Прочее", создана пользователем Kreker, 3 янв 2009.

  1. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    В первом сайте на "классах" делал global $db в каждой функции, но понимаю, что это совок.
    $this->db длинновато, учитывая, что еще будет обращение к методам.
    Научите, пожалуйста :oops:
     
  2. sword dancer

    sword dancer Активный пользователь

    С нами с:
    17 фев 2008
    Сообщения:
    295
    Симпатии:
    0
    $db= $this->db
     
  3. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Я недопонимаю просто, где присваивать ресурс. Если в конструкторе родителя, то все дочерние классы будут заново подключаться к базе. Как я понимаю, класс базы должен быть синглтоном?
     
  4. AlexGousev

    AlexGousev Активный пользователь

    С нами с:
    25 мар 2006
    Сообщения:
    1.505
    Симпатии:
    0
    Адрес:
    Москва
    Kreker
    Ну правильно, синглтоном. У тебя есть доступ к исходникам комершала? Там есть же класс Database
     
  5. sword dancer

    sword dancer Активный пользователь

    С нами с:
    17 фев 2008
    Сообщения:
    295
    Симпатии:
    0
    тебе нужно создать глобальный объект - "реестр баз данных". клиентский код будет спрашивать его "дай-ка мне объект для работы с основной базой данных". менеджер смотрит у себя в кэше и если находит нужный объект - отдаёт его, иначе - создаёт новый, прописывая все необходимые параметры (логин,пароль,хост...). далее клиентский код делает запрос. драйвер бд смотрит не открыто ли соединение, если не открыто - открывает. делает запрос и возвращает клиентскому коду "курсор". далее клиентский код запрашивает у курсора данные в нужном виде (значение поля, строку, столбец, таблицу целиком).
    как-то так :)
     
  6. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    AlexGousev
    Да я помню, там класс базы данных был синглотоном, но обращение было к нему не в конструкторе, а в каждом методе, если не ошибаюсь.

    Ну, в принципе, так и представлял :)


    Спасибо :)
     
  7. AlexGousev

    AlexGousev Активный пользователь

    С нами с:
    25 мар 2006
    Сообщения:
    1.505
    Симпатии:
    0
    Адрес:
    Москва
    sword dancer
    Где-то я это видел… только вот зачем все так сложно? :)


    Kreker
    По необходимости, конечно. Где надо, там и обращаешься. А ты как хотел, чтобы в классе был доступен как свойство? Тогда в конструкторе сделай инициализацию этого свойства и все. Правда, мне трудно представить зачем это.
     
  8. sword dancer

    sword dancer Активный пользователь

    С нами с:
    17 фев 2008
    Сообщения:
    295
    Симпатии:
    0
    да чего ж там сложного? всё просто и удобно. каждый обхект выполняет свою и только свою функцию.
    менеджер баз - обеспечивает разворачивание имени базы в параметры подключения к ней, а также единократность подключения
    драйвер бд - реализует ленивое подключение и низкоуровневое взаимодействие с субд
    курсор - ленивое вытягивание данных в удобном для клиента виде.
     
  9. sword dancer

    sword dancer Активный пользователь

    С нами с:
    17 фев 2008
    Сообщения:
    295
    Симпатии:
    0
    да ещё рекомендую составлять запросы с помощью "объектного составителя запросов", а не конкатенацией строчек - сильно упрощает работу и повышает безопасность..
     
  10. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    AlexGousev
    Я изначально выразился неправильно.
    Ресурс базы у меня и так инициализируется в конструкторе класса базы. Я имел ввиду следующее -- "где создавать экземпляр этого класса?"
    Мне кажется, что в конструкторе это наиболее удобно, если необходимо обращаться нескольким методам класса (отпадает необходимость вызывать по несколько раз синглтону проверять свое существование).

    Давно уже это читал, только перейти никак не соберусь...
     
  11. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    А разве ресурс не сериализируется?
     
  12. Hight

    Hight Старожил
    Команда форума Модератор

    С нами с:
    5 мар 2006
    Сообщения:
    7.153
    Симпатии:
    0
    Адрес:
    из злой параллельной вселенной
  13. Ребят, вы о чем? Какой еще «реестр баз данных» (хотя идея верная, просто зачем делать узкоспециализированный обьект для работы с ускоспециализированным обьектом БД) ??

    Идеология:
    http://ru.wikipedia.org/wiki/Порождающие_шаблоны_проектирования

    http://javagu.ru/portal/dt?last=false&p ... TION_80703

    В терминах PHP:
    http://mutantphp.org/blog/2008/06/19/a- ... -for-php5/

    Могу даже показать готовый код, как доберусь домой.
     
  14. сильно рекомендую начать пользоватчя PDO и плейсхолдерами.
     
  15. Sergey89

    Sergey89 Активный пользователь

    С нами с:
    4 янв 2007
    Сообщения:
    4.796
    Симпатии:
    0
  16. sword dancer

    sword dancer Активный пользователь

    С нами с:
    17 фев 2008
    Сообщения:
    295
    Симпатии:
    0
    > зачем делать узкоспециализированный обьект для работы с ускоспециализированным обьектом БД.

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


    > сильно рекомендую начать пользоватчя PDO и плейсхолдерами.

    пусть он сначала научится отличать операторы like, regexp и equal, научится принимать на вход множества значений, а не только по одной штучке, реализует возможность динамического построения запроса на основе прототипа...
     
  17. Ti

    Ti Активный пользователь

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    обычно, ООП - множество взаимодействующий объектов. Создавать объект базы данных в конструкторе каждого объекта - не очень хорошая идея

    db::getInstance() будет еще длинее. В награду не будет глобальной переменной, а подключение к базе будет происходить при необходимости.
    PHP:
    1. <?
    2. // $db - короткое имя
    3. $db = db::getInstance();
    4.  
    5. // если в методе используется один раз разумно не присваивать переменной
    6. foreach(db::getInstance()->query($sql) as $line) {
    7.    //...
    8. }
    9.  
    минимальный вариант метода getInstance:
    PHP:
    1. <?
    2. class db {
    3.     static private $instance;
    4.  
    5.  
    6.     /**
    7.      * @return db
    8.      */
    9.     static function getInstance() {
    10.         if (is_null(self::$instance)) self::$instance = new self;
    11.         return self::$instance;
    12.     }
    13.  
    14.  
    15.     // ...
    16. }
     
  18. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Ti
    Спасибо) В принципе я все это уже ни раз читал, просто было интересно в плане правильности с точки зрения ООП.
    Это мне и было интересно.

    Спасибо всем за советы. Принял все советы к сведению. Посмотрю ваши цмски подробнее в этом плане.

    флоппик
    Было бы интересно посмотреть, как ты организовался в "простом" движке, буду ждать download-сборки :)

    P.S. Блин, сколько всего еще читать и разбирать... где ты, время?
     
  19. sword dancer

    sword dancer Активный пользователь

    С нами с:
    17 фев 2008
    Сообщения:
    295
    Симпатии:
    0
    > db::getInstance() будет еще длинее. В награду не будет глобальной переменной

    будет глобальная константа. уже предвижу проблемы с реализацией мок-тестов.
     
  20. Ti

    Ti Активный пользователь

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    константа?

    Это "минимальный вариант".
    Добавив реестр (без изменения API), конечно, будет более гибко.
    Но делать это только из-за юнит тестов - десять раз подумать.
    Да и черевато юзать в тестах мок-объект базы данных - обычно юзают тестовую базу.
     
  21. sword dancer

    sword dancer Активный пользователь

    С нами с:
    17 фев 2008
    Сообщения:
    295
    Симпатии:
    0
    db - константа, засоряющая собой глобальный неймспейс. вероятность того, что кому-то ещё придёт в голову создать класс с таким именем - довольно высока.

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

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

    Ti Активный пользователь

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    sword dancer
    Оффтоп. Вы прыгаете с темы на тему.
    Проблема именования классов и namespace не относится к вопросу, так же как и тестирование.

    Префиксы никто не отменял.
    У Вас правда есть какое то предложение которое решает проблему namespace в данном случае?
    Мой пример "минимальный вариант метода getInstance" - простой и наглядный, Ваши придирки не уместны.

    Частный пример - метод объекта вставляет запись. Дуализм отдыхает.
    Конечно, если использовать ORM, логично в тестах подменять его мок объектом. Но тесты самого ORM однозначно должны работать на реальной базе данных.

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

    Не правда, проблема выявляется сразу, не добавляя хрупкости тестам.
     
  23. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Вот я тоже прочитал про плейсхолдеры, загорелся написать удобный класс, но запоролся на том, что нужно результаты биндить в переменные.
    Если не указывать вручную, а делать автоматически, то нужно выяснять, сколько возвращено полей и их имена, потом набивать их в массив и отдавать для функции бинда. А после и превращать в обычный массив. Где удобство? Почему нет обычного fetch_array?
     
  24. Пардон, нахрена? возьми PDO и напиши удобный класс вокруг него. И если база поддерживает нативные плейсхолдеры, драйвер задействует их (что будет очень быстро работать), нет, так он из будет сам контролировать....
     
  25. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Поверхностно просмотрел я PDO, не очень мне понравилось. Даже если и его приспособить под себя с помощью обертки, все равно получится не очень хорошо в плане количества кода и изящности решения :) Да и еще, я же чмо болотное, мне надо велосипеды поизобретать. Свое ближе к телу. Хочу научиться сначала делать свое, прежде чем юзать чужое. И mysqli_stmt. Буду сейчас свой "драйвер" писать с подготовленными выражениями.