Переписываю заново довольно крупный проект, поэтому встал вопрос о том как лучше использовать классы. Напишу сразу на живом примере, так будет понятнее, что именно я бы хотел у вас узнать. У меня есть классы Mysql (с функциями базы данных) и System (с функциями которые используются на любой странице сайта). Для каждого из крупных разделов сайта я создаю класс, например Новости , Вопросы, Обновления. Наследование получается таким: Mysql -> System -> Новости Mysql -> System -> Вопросы Mysql -> System -> Обновления Но тут у меня появился класс Комментарии, функциями которого я хочу, чтобы умели пользоваться Новости. Здесь я столкнулся с дилеммой. Можно сделать так: Mysql -> System -> Комментарии -> Новости А можно так: Mysql -> Комментарии Mysql -> System -> Новости (с объявлением внутри объекта $comments = new Комметарии и его использованием) В первом варианте меня смущает, что при появлении еще одного класса для новостей вроде Комметариев (например Голосование) получится так: Mysql -> System -> Комментарии -> Голосование -> Новости. А это значит, что голосование всегда будет наследовать комментарии, а не должно. Во втором варианте меня смущает, что mysql класс наследуется дважды (один раз новостями, другой раз комментариями), а следовательно получится, что подключения к базе будет 2. Так как проект крупный и посещаемость большая, то лишние коннекты ни к чему. Быть может где-то я ошибаюсь в своих рассуждениях или не рассматриваю какой-нибудь третий более оптимальный вариант. Как бы в такой ситуации поступили бы вы?
У вас каждый класс свое подключение создает? Если так, то это неверный подход. Коннект один должен быть, да и вообще все запросы должны через один класс идти. Обычно делается Синглтон для таких вещей. А остальные классы уже пользуются его методами
С MVC знаком, а про ServiceLocator и Dependency Injection почитал немного, выглядит заманчиво, но довольно расплывчатую информацию пока нашел. Не совсем пока понял как их воспринимать, как готовые паттерны, которые нужно взять и пользоваться или как подход на основе которого надо написать свой код. Методы работы с базой данных описаны только в классе Mysql, а другие классы их наследуют и пользуются. Коннект к базе происходит в конструкторе класса MySQL. В конструкторе других классов вызывается конструктор родителя. Например, объект Новости при создании вызывает конструктор объекта System, а конструктор System вызывает конструктор MySQL, который создает соединение. Чую, что как-то мутно получается, поэтому и написал сюда. Правильно ли я понимаю применение Singleton? Каждый из классов обращается к Singleton, который если объект класса Mysql не существует - создаст его, а если существует, то будет работать через него? То есть в моем конкретном примере он будет вызываться Новостями и Комментариями. В случае если используются только Комментарии, то они создадут MySQL объект через singleton. А если же в составе новостей, то до этого его создадут Новости, а Комментарии будут уже им пользоваться? Прошу прощения, если в моей голове картина происходящего вдруг отклоняется от действительности)
Kotoffsky статики рулят в таком деле. даже экземпляр класса создавать не нужно =) и доступны везде без глобальности.
Этот конструктор родителя как раз и будет создавать новое подключение в каждом классе, а это не есть гуд. Да, примерно так и есть. При первом обращении создается синглтон(в нем соединение с базой). При повторном обращении проверяется - если объект уже создан (подключение к базе есть), то возвращается этот объект. Если нет - создается. http://ru.wikipedia.org/wiki/%D0%A1%D0% ... 0%BE%D0%BD Можно и статику использовать, как igordata сказал. Это тоже широко применимо. Само подключение сделать функцией, а уже запросы - статическими методами класса MySql
В общем случае - да. Но я видел систему, где доступ контролировался мускулом (на каждый модуль свой mysql-акк). Работало шустро и уровень защиты высокий. Решение мне не очень нравится, но рациональное зерно в этом есть.
titch Профилировал работу с базой на одном из своих проектов. Большинство запросов - менее 0,01 сек (без Джоинов, индексы стоят). Тогда как соединение с базой - 0,2 может занять. обычно на одну страницу сколько запросов приходится? 10-12 как максимум? Имхо для 10 запросов 4 подключения делать - переборчик))))
titch зависит от задачи. На новостном сайте наверное нет смысла в такой крутой штуке. Но сам всегда задумываюсь о реализации на нескольких аккаунтах.
Всем спасибо за ответы. Singleton и вправду хорошо вписывается в то что уже есть. Так что пока буду реализовывать так: Класс Singleton будет содержать статичную функцию getInstance() (как на википедии). Класс Mysql extends Singleton и в конструкторе содержит подключение. В свою очередь Mysql уже никто наследовать не будет, а будут вызывать MySQL::getInstance(). Остальные классы выходят так: System -> Новости (с объектом $comments = new Комментарии) System -> Вопросы System -> Обновления Другие варианты реализации буду тоже держать в голове на случай непредвиденных обстоятельств)
Kotoffsky мускул вполне можно сделать статиком. статик не забывает. =) просто после объявления класса сразу можно написать подключение и забыть о том что он статик. И все будет круто.
Kotoffsky Как вариант - внутри класса Mysql содержится объект Singleton. В конструкторе он вызывается через getInstance(). Остальные классы наследуются от Mysql В итоге - внутри всех конструкторов будет вызываться один и тот же объект Singleton, зато функции Mysql будут доступны через $this
Kotoffsky Скорее всего нужно не наследование, а включение. Возможно статика igordata Пляшет и поет, пока не понадобится второе подключение.
Volt(220) если количество подключений заранее известны, то все просто. Если нет, то все равно можно юзать один статик класс, переключая отдельным методом, или выбирая подключение сразу в методе запроса, фигли =)
igordata Да без проблем. Но подход с наличием двух(и более) объектов мне кажется более понятным и простым чем всякие переключения... У меня изначально была задача работать с двумя базами в итоге получилась фабрика: Код (Text): SQLDBFactory::getDB(); вернет подключение по конфигу из настроек (если его еще нет то создаст) Код (Text): SQLDBFactory::getDB($config); создаст новое подключение с параметрами $config. Код (Text): SQLDBFactory::getAlterDB(); Вернет подключение ко второй базе (если его еще нет то создаст).