Наилучший практический подход к связыванию запросов соединения MySQL с ООП и объектами


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

У меня есть таблицы MySQL для Destinations, Trips, и Users, и таблицу под названием Invites для разрешения отношения "многие ко многим" между Users и Trips.

Для каждой из этих таблиц я создал класс в своем приложении (так что Destinations - это класс, Trips - это класс и т. Д.). Я написал статическую функцию для каждого из этих классов, которая позволяет объектам должны быть созданы экземпляры и их свойства назначены из запроса MySQL (поэтому каждая строка, возвращаемая из запроса SELECT *, приводит к созданию экземпляра объекта и назначению свойств).

Я пытаюсь создать страницу, на которой мой пользователь сможет просмотреть подробную информацию обо всех запланированных им поездках. На этой странице будет показан пункт назначения (из Destinations), сведения о поездке (например, дата из Trips) и сведения о пользователях, которых они пригласили (например, имя пользователя из Users), и все эти данные будут помещены в таблицу html, где каждая поездка - это ряд.

Для достижения этой цели до сих пор я создавал экземпляры Trips, которые относятся к пользовательским user_id, Destinations и Invites, которые относятся к тем Trips, и Users, которые относятся к тем Invites. Затем я использовал вложенные циклы foreach для отображения их по мере необходимости, например, ниже:

foreach($trips as $trip) {
 foreach($invites as $invite) {
   foreach($invited_users as $invited_user) {
      if($invite->trip_id == $trip->id && $invite->guest_id == $invited_user->id) {
        echo $invited_user->name;
                  } } } }

Что, как я вижу, ужасно, и это невозможно сделать.

Прочитав, я думаю, что хочу использовать MySQL для объединения 4 таблиц, а затем выбрать только данные, относящиеся к моим соответствующим поездки. Но в чем я не уверен, так это в следующем:

A) Как мне создать экземпляр объектов и правильно назначить их свойства из этого результата MySQL?

Б) Даже если это сделано, как мне избежать дорогостоящих foreach циклов для отображения правильных данных вместе с правильной поездкой?

Существует ли "наилучший" способ отображения данных из нескольких связанных таблиц базы данных объектно-ориентированным способом?

Author: Jay, 2012-11-12

2 answers

Я думаю, что вы все усложняете, вам не нужно загружать все данные сразу.

Зачем перебирать все поездки, в то время как вам нужно отобразить поездки одного пользователя?

Наивный, но простой подход с помощью ООП: класс User с методом извлечения связанных поездок пользователя.

Он может возвращать массив Trip, содержащий ссылки на приглашенных пользователей:

class User {
    private $id;
    public function __construct($id) {
        $this->id = $id;
    }
    public function getTrips() {
        $trips = array();
        // Run your query using $this->id to build the WHERE clause
        return $trips;
    }
}

class Trip {

    // Array of User objects invited to the trip        
    private $invited = array();

    // Other methods here to add/retrieve invited users

}

$user = new User(1);
foreach ($user->getTrips() as $trip) {
    // Do something with $trip
}

В идеале экземпляр User должен храниться в сеансе

 0
Author: mexique1, 2012-11-11 21:06:26

Во-первых, "хорошая практика" - это одна из тех фраз, которые люди используют, чтобы придать своим предрассудкам видимость респектабельности. Лучше спросить, как достичь конкретных целей с помощью дизайна.

Сказав это: вы столкнулись с проблемой, которая часто встречается при сопоставлении СУБД с объектно-ориентированной системой. Google "Ленивая загрузка" для большого обсуждения. Вопрос сводится к вопросу о том, сколько "отношений" вы загружаете одновременно. В вашем примере поездки связаны с пункты назначения и пользователи; при загрузке "поездки" следует ли также загружать пункты назначения и пользователей? И если вы это сделаете, следует ли вам также загружать другую информацию для пользователя (например, о других поездках, в которых они участвуют?). И если да, загружаете ли вы данные о поездках для всех поездок, в которых находится пользователь? И так далее - если вы не будете осторожны, вы в конечном итоге загрузите всю базу данных.

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

Для подробного описания того, что я считаю лучшей практикой, купите и прочитайте "Дизайн, управляемый доменом" Эванса.

В качестве ярлыка рассмотрите возможность создания слоя "репозиторий", который знает, как сопоставлять записи базы данных с объектами, и создайте пользовательские методы для поиска того, что вы хотите. Например, вы можете вызвать:

$repository::getTripsForUser($userID);

Этот метод выполнит SQL-запрос, соединяющий 4 таблицы вместе, и превратит результаты в дерево объектов.

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

 2
Author: Neville Kuyt, 2012-11-11 21:25:28