2

在我的 PHP MVC 应用程序中,我有三个主要实体:组织、员工和角色。每个组织都有很多员工,每个员工都有一个角色。

对于给定的组织,我想显示员工列表。对于每个员工,我将显示姓名、地址详细信息和角色名称。

现在,据我所知,最有效的方法是让我的服务层将员工列表作为数组返回,其中每个元素都是数据字段数组(不是对象)。在映射器中,我将角色表连接到员工表,因此正确的角色名称将在初始结果集中,并且无需再次查询数据库。

另一种方法是让我的服务层返回 Employee 对象的集合。但是,在这种情况下,每个 Employee 对象都需要查询数据库以找到其角色的正确名称(假设角色是延迟加载的)。这将是非常低效的,但不知何故似乎更“面向对象”。

每当实例化 Employee 时,我可以考虑将角色名称加载为 Employee 的属性,但是我仍然需要保留对唯一角色 ID 的引用,因此我立即有同步考虑。

解决这个问题的典型方法是什么???我相信它已经解决了数百万次!

谢谢!

4

1 回答 1

1

的确,这东西很标准。但我仍然与它斗争。

我的第一个想法是设置类似:

class Employee 
{
    protected $name; //etc

    /**
     * @var Organization
     */
    protected $organization;

    /**
     * @var Role
     */
    protected $role;

    // And then getters/setters for Role and Organization
}

然后一个 EmployeeMapper 类似:

class EmployeeMapper
{
    /**
     * @Var DB
     */
    protectd $db;

    public function __construct(DB $db)
    {
        $this->db = $db
    }

    public function getEmployeesByOrganization($orgId)
    {
        // query here that joins employees, roles, and organizations
    }
}

这让我觉得很干净,代表了你描述的结构。

但是这样做的问题是,当 EmployeeMapper 必须构造 Employee 对象时,他需要知道连接的查询结果中的角色字段和组织字段如何映射到角色和组织对象中的字段。对我来说,这些知识应该严格地存在于 RoleMapper 和 OrganizationMapper 中。因此,也许这些映射器需要将此映射功能作为公共方法提供,我们需要有一种方法将 RoleMapper 和 OrganizationMapper 实例注入到 EmployeeMapper 中以供使用。有关基于 ZF 的示例,请参阅生存深渊

此外,似乎有时 - 如您提供的“查看员工列表”示例中 - 您希望获得有关这些附加角色和组织实体的信息。在这种情况下,加入和构建对象图的开销是合理的,并且(肯定比为角色和组织进行单独的循环查询更好)。但在其他情况下,您实际上只需要单个员工的一些简单员工信息,例如他的姓名或电话号码。在后一种情况下,为什么会产生加入和构建完整对象图的开销?

这些问题有一些架构解决方案,通常使用代理对象(代表角色和组织对象并在需要时延迟加载它们)和自定义存储库对象(您想要强制连接的地方)。

但我发现自己设计这一切是一件痛苦的事。最后,我发现像Doctrine这样的 ORM已经解决了所有问题,并为我提供了上述功能(代理、自定义存储库等)。

于 2013-02-25T02:47:12.310 回答