1

我有这两个数据库表:

位置
ID
名称

用户
id
location_id
last_name
first_name

我也有UserLocation类,它们都扩展了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 查询性能问题。

我怎样才能用最少的代码做到这一点?

注意:我制作这个示例只是为了演示目的,在我的真实案例中,有很多表和类(其中定义了自定义方法)。

非常感谢大家。

4

3 回答 3

2

你考虑过以下几点吗?

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;

    }

}

这样,除非您需要数据,否则您完全避免了加载位置表的开销,在这种情况下,您将其缓存在对象中以备将来使用。

于 2012-05-29T16:37:30.590 回答
0

我对自己提出了同样的问题,但发现最简单的方法是遍历每个结果(在您的情况下为用户)并选择相应的子对象(位置)并设置为父对象中的字段(用户->位置)。

我能想到的唯一替代方法是编辑(或扩展和创建您自己的数据库集)db_result 类以使用 getters/setters 而不是直接字段 - 也许使用 call_user_func_array()。此时,您可以在用户模型中编写 setId() 函数,以便在接收到 userId/外键时设置 $location 字段。

于 2011-10-12T22:39:11.147 回答
0

从表用户获取位置 id,使用它的编号通过 id 对象从表位置中获取。并放入其中。

于 2016-03-31T18:05:20.387 回答