对象关系映射:What';It是实现getter的最佳方法


Object-relational mapping: What's the best way to implement getters?

当我调用$user->get_email_address()时应该发生什么

选项1:根据需要从数据库中提取电子邮件地址

public function get_email_address() {
    if (!$this->email_address) {
        $this->read_from_database('email_address');
    }
    return $this->email_address;
}

选项2:在创建对象时从数据库中提取电子邮件地址(和其他用户属性)

public function __construct(..., $id = 0) {
    if ($id) {
        $this->load_all_data_from_db($id);
    }
}
public function get_email_address() {
    return $this->email_address;
}

我的基本问题是,是最好尽量减少数据库查询的数量,还是最好尽量减少从数据库传输的数据量。

另一种可能性是,最好在创建对象时加载需要最多/包含最少数据的属性,并根据需要加载其他所有属性。

后续问题:像Activerecord这样的ORM抽象框架做什么?

这真的没有一个正确的答案。取决于一次加载的用户数量、用户表中有多少文本/blob字段,以及用户表是否加载任何关联的子对象。正如aaronjensen所说,这种模式被称为懒惰加载,而相反的行为(提前加载所有东西,以备不时之需)被称为渴望加载

也就是说,您可能需要考虑第三种选择,即在访问其任何属性时延迟加载整个User对象:

public function get_email_address() {
    if (!$this->email_address) {
        $this->load_all_data_from_db($this->id)
    }
    return $this->email_address;
}

这种方法的优点是,您可以仅根据用户的ID创建一个用户集合(例如,密码为空的所有用户的列表,可能是?),而不需要完全加载每个用户的内存,但您只需要为每个用户调用一个数据库来填充其余的用户字段。

最大限度地减少查询数量。查询的最佳数量为0,但如果因为未缓存而必须进行查询,则为1。查询每一个属性对于一个永远不会扩展、存在大量争用问题、并且会造成比其价值更大的麻烦的系统来说,无疑是一种很好的方法。

我应该提到的是,延迟加载(这就是您在步骤1中所说的)是有价值的,如果您不太可能需要延迟加载数据。如果可以的话,最好是明确,准确或几乎准确地获取你需要的东西。查询时间越短,连接打开的时间就越短,系统的可扩展性就越强。

我同意aaronjensen的观点,除非你提取的数据量太大,以至于你会开始消耗过多的内存。我在想一行有3个文本字段,它们都很大,而您只需要ID字段。