В первом сайте на "классах" делал global $db в каждой функции, но понимаю, что это совок. $this->db длинновато, учитывая, что еще будет обращение к методам. Научите, пожалуйста
Я недопонимаю просто, где присваивать ресурс. Если в конструкторе родителя, то все дочерние классы будут заново подключаться к базе. Как я понимаю, класс базы должен быть синглтоном?
Kreker Ну правильно, синглтоном. У тебя есть доступ к исходникам комершала? Там есть же класс Database
тебе нужно создать глобальный объект - "реестр баз данных". клиентский код будет спрашивать его "дай-ка мне объект для работы с основной базой данных". менеджер смотрит у себя в кэше и если находит нужный объект - отдаёт его, иначе - создаёт новый, прописывая все необходимые параметры (логин,пароль,хост...). далее клиентский код делает запрос. драйвер бд смотрит не открыто ли соединение, если не открыто - открывает. делает запрос и возвращает клиентскому коду "курсор". далее клиентский код запрашивает у курсора данные в нужном виде (значение поля, строку, столбец, таблицу целиком). как-то так
AlexGousev Да я помню, там класс базы данных был синглотоном, но обращение было к нему не в конструкторе, а в каждом методе, если не ошибаюсь. Ну, в принципе, так и представлял Спасибо
sword dancer Где-то я это видел… только вот зачем все так сложно? Kreker По необходимости, конечно. Где надо, там и обращаешься. А ты как хотел, чтобы в классе был доступен как свойство? Тогда в конструкторе сделай инициализацию этого свойства и все. Правда, мне трудно представить зачем это.
да чего ж там сложного? всё просто и удобно. каждый обхект выполняет свою и только свою функцию. менеджер баз - обеспечивает разворачивание имени базы в параметры подключения к ней, а также единократность подключения драйвер бд - реализует ленивое подключение и низкоуровневое взаимодействие с субд курсор - ленивое вытягивание данных в удобном для клиента виде.
да ещё рекомендую составлять запросы с помощью "объектного составителя запросов", а не конкатенацией строчек - сильно упрощает работу и повышает безопасность..
AlexGousev Я изначально выразился неправильно. Ресурс базы у меня и так инициализируется в конструкторе класса базы. Я имел ввиду следующее -- "где создавать экземпляр этого класса?" Мне кажется, что в конструкторе это наиболее удобно, если необходимо обращаться нескольким методам класса (отпадает необходимость вызывать по несколько раз синглтону проверять свое существование). Давно уже это читал, только перейти никак не соберусь...
Ребят, вы о чем? Какой еще «реестр баз данных» (хотя идея верная, просто зачем делать узкоспециализированный обьект для работы с ускоспециализированным обьектом БД) ?? Идеология: 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/ Могу даже показать готовый код, как доберусь домой.
> зачем делать узкоспециализированный обьект для работы с ускоспециализированным обьектом БД. а зачем делать широкоспециализированный объект, который занимается всем по немногу? > сильно рекомендую начать пользоватчя PDO и плейсхолдерами. пусть он сначала научится отличать операторы like, regexp и equal, научится принимать на вход множества значений, а не только по одной штучке, реализует возможность динамического построения запроса на основе прототипа...
обычно, ООП - множество взаимодействующий объектов. Создавать объект базы данных в конструкторе каждого объекта - не очень хорошая идея db::getInstance() будет еще длинее. В награду не будет глобальной переменной, а подключение к базе будет происходить при необходимости. PHP: <? // $db - короткое имя $db = db::getInstance(); // если в методе используется один раз разумно не присваивать переменной foreach(db::getInstance()->query($sql) as $line) { //... } минимальный вариант метода getInstance: PHP: <? class db { static private $instance; /** * @return db */ static function getInstance() { if (is_null(self::$instance)) self::$instance = new self; return self::$instance; } // ... }
Ti Спасибо) В принципе я все это уже ни раз читал, просто было интересно в плане правильности с точки зрения ООП. Это мне и было интересно. Спасибо всем за советы. Принял все советы к сведению. Посмотрю ваши цмски подробнее в этом плане. флоппик Было бы интересно посмотреть, как ты организовался в "простом" движке, буду ждать download-сборки P.S. Блин, сколько всего еще читать и разбирать... где ты, время?
> db::getInstance() будет еще длинее. В награду не будет глобальной переменной будет глобальная константа. уже предвижу проблемы с реализацией мок-тестов.
константа? Это "минимальный вариант". Добавив реестр (без изменения API), конечно, будет более гибко. Но делать это только из-за юнит тестов - десять раз подумать. Да и черевато юзать в тестах мок-объект базы данных - обычно юзают тестовую базу.
db - константа, засоряющая собой глобальный неймспейс. вероятность того, что кому-то ещё придёт в голову создать класс с таким именем - довольно высока. хороший тест тестирует только один аспект. если юзать тестовую базу, то непрохождение теста может означать: - ошибку в тестируемом объекте - ошибку в тестовой базе и наоборот - особенности базы могут вуалировать ошибку в объекте. также поломка базы с высокой вероятностью загубит большую часть тестов и будет трудно понять виноват ли какой-то сильно реюзабельный метод, база, конфигурация сервера или ещё что-то. хороший тест должен не просто показывать, что что-то сломалось, а указывать в каком именно месте произошла поломка. поэтому нужны отдельно тесты для базы и отдельно тесты для остальных объектов.
sword dancer Оффтоп. Вы прыгаете с темы на тему. Проблема именования классов и namespace не относится к вопросу, так же как и тестирование. Префиксы никто не отменял. У Вас правда есть какое то предложение которое решает проблему namespace в данном случае? Мой пример "минимальный вариант метода getInstance" - простой и наглядный, Ваши придирки не уместны. Частный пример - метод объекта вставляет запись. Дуализм отдыхает. Конечно, если использовать ORM, логично в тестах подменять его мок объектом. Но тесты самого ORM однозначно должны работать на реальной базе данных. Вот именно, если писать отдельные тесты для базы, сложно гарантировать функционал и покрытие тестов, эффективней тестировать готовую связку с базой данных Не правда, проблема выявляется сразу, не добавляя хрупкости тестам.
Вот я тоже прочитал про плейсхолдеры, загорелся написать удобный класс, но запоролся на том, что нужно результаты биндить в переменные. Если не указывать вручную, а делать автоматически, то нужно выяснять, сколько возвращено полей и их имена, потом набивать их в массив и отдавать для функции бинда. А после и превращать в обычный массив. Где удобство? Почему нет обычного fetch_array?
Пардон, нахрена? возьми PDO и напиши удобный класс вокруг него. И если база поддерживает нативные плейсхолдеры, драйвер задействует их (что будет очень быстро работать), нет, так он из будет сам контролировать....
Поверхностно просмотрел я PDO, не очень мне понравилось. Даже если и его приспособить под себя с помощью обертки, все равно получится не очень хорошо в плане количества кода и изящности решения Да и еще, я же чмо болотное, мне надо велосипеды поизобретать. Свое ближе к телу. Хочу научиться сначала делать свое, прежде чем юзать чужое. И mysqli_stmt. Буду сейчас свой "драйвер" писать с подготовленными выражениями.