Поэтому я пытаюсь использовать хорошие методы объектно-ориентированного программирования с помощью PHP. Большинство (все) моих проектов связаны с базой данных MySQL. Моя непосредственная проблема связана с моделью пользователей, которую мне нужно разработать.
В моем текущем проекте есть агенты и руководители. Как агенты, так и руководители – это пользователи с большей частью той же информации. Поэтому, очевидно, я хочу, чтобы агенты класса и класс приводили к расширению общего класса Users. Теперь, мой вопрос заключается в следующем:
Как лучше всего обрабатывать SQL для загрузки этих объектов? Я не хочу выполнять несколько операторов SQL при создании экземпляра агента или ведущего. Однако логика подсказывает мне, что при запуске конструктора Users он должен выполнить инструкцию SQL для загрузки общей информации между агентами и проводниками (имя пользователя, пароль, электронная почта, контактная информация и т. Д.). Logic также сообщает мне, что при запуске конструктора Agents или Leads я хочу выполнить SQL, чтобы загрузить данные, уникальные для класса Agents или Leads … Но опять же логика также говорит мне, что это плохая идея выполнить 2 SQL-запросов каждый раз, когда мне нужен агент или ведущий (так как могут быть тысячи).
Я попытался найти примеры того, как это обычно обрабатывается без успеха … Возможно, я просто искал неправильную вещь?
У вас в основном есть три подхода к этой проблеме (один из которых я немедленно устраню):
Для простоты я обычно рекомендую (2). Итак, как только у вас есть таблица:
CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, type VARCHAR(10), name VARCHAR(100) );
где тип может быть «AGENT» или «LEAD» (например). В качестве альтернативы вы можете использовать один код типа символа. Затем вы можете начать заполнять пробелы с помощью объектной модели:
и он должен легко встать на свои места.
Что касается загрузки в одном заявлении, я бы использовал какой-то завод. Предполагая эти классы barebones:
class User { private $name; private $type; protected __construct($query) { $this->type = $query['type']; $this->name = $query['name']; } ... } class Agent { private $agency; public __construct($query) { parent::constructor($query); $this->agency = $query['agency']; } ... } class Lead { public __consruct($query) { parent::constructor($query); } ... }
фабрика может выглядеть так:
public function loadUserById($id) { $id = mysql_real_escape_string($id); // just in case $sql = "SELECT * FROM user WHERE id = $id"; $query = mysql_query($sql); if (!query) { die("Error executing $sql - " . mysql_error()); } if ($query['type'] == 'AGENT') { return new Agent($query); } else if ($query['type'] == 'LEAD') { return new Lead($query); } else { die("Unknown user type '$query[type]'"); } }
В качестве альтернативы вы можете использовать метод factory как статический метод, например, для класса User и / или использовать таблицу поиска для типов для классов.
Возможно, загрязнение классов ресурсом результата запроса, как это, является сомнительным дизайном в строгом смысле OO, но это просто и работает.
Будет ли у вас когда-нибудь пользователь, который не является руководителем или агентом? Действительно ли этому классу действительно нужно извлекать данные из базы данных?
Если это так, почему бы не вытащить SQL-запрос в функцию, которую вы можете переопределить при создании дочернего класса.
Не могли бы вы наследовать сказать скелет SQL, а затем использовать функцию в каждом подклассе для завершения запроса на основе его потребностей?
Используя действительно базовый пример:
<?php //our query which could be defined in superclass $query = "SELECT :field FROM :table WHERE :condition"; //in our subclass $field = "user, password, email"; $table = "agent"; $condition = "name = 'jim'"; $dbh->prepare($query); $sth->bindParam(':field', $field); $sth->bindParam....;//etc $sth->execute(); ?>
и<?php //our query which could be defined in superclass $query = "SELECT :field FROM :table WHERE :condition"; //in our subclass $field = "user, password, email"; $table = "agent"; $condition = "name = 'jim'"; $dbh->prepare($query); $sth->bindParam(':field', $field); $sth->bindParam....;//etc $sth->execute(); ?>
Как вы можете видеть, мой пример не удивительный, но должен позволить вам увидеть, что я получаю. Если ваш запрос очень похож между подклассами, я думаю, что мое предложение может работать.
Очевидно, что это потребует некоторой настройки, но это, вероятно, подход, который я бы взял.