在Codeigniter Active记录中通过join返回的自定义对象

时间:2011-07-05 03:58:10

标签: php codeigniter orm codeigniter-2

我有这两个数据库表:

地点
ID
命名

用户
ID
LOCATION_ID
姓氏
如first_name

我还有用户位置类,它们都扩展了模型并包含一些自定义方法。例如,用户类中有 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现在是用户对象的一个​​字段,我想要的是用户对象的字段为位置允许我像这样使用它的对象,

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查询性能问题。

如何以最少的代码执行此操作?

注意:我为了演示目的而编写了这个例子,在我的实际情况中,有很多表和类(它们上面定义了自定义方法)。

非常感谢大家。

3 个答案:

答案 0 :(得分: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;

    }

}

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

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

从表用户获取位置ID,使用它的数字通过id对象从表位置获取。并把它放进去。