您正在寻找的关键字是eager loading与lazy loading。
简而言之:
- Eager Loading 是您目前正在做的事情:创建对象后,您将加载所有相关的对象和属性,无论需要多长时间。
- 延迟加载则相反:您只会在需要时加载信息。(瞬间,真的是被访问了)
--
两者的(非常基本的)实现看起来像下面的示例。
//Data Model
abstract class UserModel{
protected $userData = null;
protected $userPosts = null;
protected function loadUserData(){
//do whatever required and store in $result
$this->userData = $result;
}
protected function loadUserPosts(){
//do whatever required and store in $result
$this->userPosts = $result;
}
public abstract function getUserData();
public abstract function getUserPosts();
}
//Eager Loading
class EagerUserModel extends UserModel {
public function __construct() {
$this->loadUserData()
$this->loadUserPosts();
}
public function getUserData(){
return $this->userData;
}
public function getUserPosts(){
return $this->userPosts;
}
}
//Lazy Loading
class LazyUserModel extends UserModel {
public function __construct() {
//do nothing
}
public function getUserData(){
if ($this->userData == null){
$this->loadUserData();
}
return $this->userData;
}
public function getUserPosts(){
if ($this->userPosts== null){
$this->loadUserPosts();
}
return $this->userPosts;
}
}
该示例将允许两种方式。但是,如果您不想“选择”使用哪种类型,则可以在单个类中实现急切或延迟加载。
Eager Loading 的优势在于每个信息都“就在那儿”。然而,延迟加载需要更复杂的架构。要加载“UserPosts”,您可能需要有关用户的其他数据,这意味着您必须首先加载 UserData。这是您需要考虑的事情!
那么,延迟加载总是更快?
不!这就是陷阱。想象一下,你有一个有 10 个属性的类。如果您以惰性方式加载每个属性,则需要触发 10 个 SQL 查询(SELECT Name FROM user...
等等SELECT email FROM user...
)。以一种急切的方式执行此操作,将只允许您运行 ONE Query: Select Name, email FROM user...
。
您必须找到两种方法之间的平衡。异物是否紧密耦合?(即用户 <-> 组)?-> 加载渴望。外来对象是否松散耦合(用户 -> 图片 545458 上的帖子) -> 加载惰性。
另请注意,这是一个极端的例子(100% 渴望与 100% 懒惰)。在实践中,您可能想要加载一些急切的东西(用户数据、组分配)和其他懒惰的东西(评论、组权限)——您不能为每个用例创建自己的基类扩展。然而,拥有一个“BaseClass”总是一个好主意,因为它为您提供了灵活性,无论何时需要另一个实现。