Пользовательский объект, возвращаемый объединением в активной записи Codeigniter

У меня есть эти две таблицы базы данных:

местоположения
идентификатор
имя

пользователи
id
location_id
last_name
first_name

У меня также есть классы User и Location, они оба расширяют Model и содержат некоторые пользовательские методы. Например, в классе User есть метод get_full_name().

Я использую следующие коды для загрузки данных,

$this->db->select('users.id, locations.name as location_name, users.last_name, users.first_name');
$this->db->from('users');
$this->db->join('locations', 'users.location_id = location.id');
$query = $this->db->get();
$users= $query->custom_result_object('User'); //now $users is an array of User object

custom_result_object — это встроенная, но недокументированная функция в Codeigniter. Он принимает строку имени класса и будет использовать ее для создания объектов этого класса.

С помощью приведенных выше кодов я могу получить доступ к данным следующим образом:

foreach($users as $user)
{
 echo $user->id;
 echo $user->get_full_name();
 echo $user->location_name;
}

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

foreach($users as $user)
{
 echo $user->id;
 echo $user->get_full_name();
 echo $user->location->name; // Location is an object
}

Я не хочу использовать DataMapper ORM или любые другие ORM, а также хотел бы избежать проблем с производительностью запросов N+1.

Как это сделать с минимальным количеством кодов?

Примечание. Я создал этот пример только для демонстрационных целей, в моем реальном случае существует довольно много таблиц и классов (для которых определены пользовательские методы).

Большое спасибо всем вам.


person bobo    schedule 05.07.2011    source источник


Ответы (3)


Я спрашивал то же самое для себя, но обнаружил, что самым простым способом было перебрать каждый результат (в вашем случае, пользователя), выбрать соответствующий дочерний элемент (местоположение) и установить поле в родительском объекте (пользователь- > местоположение).

Единственный альтернативный способ, который я могу придумать, - это редактирование (или расширение и создание собственного набора баз данных) класса db_result для использования геттеров/сеттеров вместо прямых полей - возможно, с помощью call_user_func_array(). В этот момент вы можете закодировать свою функцию setId() в пользовательской модели, чтобы установить поле $location после получения userId/внешнего ключа.

person dispake    schedule 12.10.2011

Рассматривали ли вы следующее?

class User {

    var location;

    public function location()
    {
        if ( empty($this->location) )
        {
            $ci =& get_instance(); 
            $this->location = $ci->db->get_where('locations', array('id' => $this->location_id))->row();
        }

        return $this->location;

    }

}

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

person Douglas Linsmeyer    schedule 29.05.2012
comment
так это входит в библиотеки? - person Zalaboza; 30.01.2014

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

person Community    schedule 31.03.2016
comment
помните, что результат () и результат_массив () не равны stackoverflow.com/questions/16506789 - person ; 31.03.2016