php - 如何使用 Data Mapper 模式延迟加载子对象?

标签 php lazy-loading datamapper

如果我有一个相当复杂的用户模型,我想使用数据映射模式来加载,我如何在不允许用户知道 UserMapper 的情况下延迟加载一些更密集的用户信息位?

例如 - 如果 User 模型允许一个地址对象数组(并且 User 可能有很多,但不一定是预先需要的),如果/当需要时我将如何加载这些对象?

我是否让用户模型知道 AddressMapper?

我是否将 User 模型传回 UserMapper,然后只对地址进行水合?

还有更好的选择吗?

最佳答案

好吧,我一次发现了以下巧妙的模式,由 Ben Scholzen 提供,Zend Framework 的开发人员。它是这样的:

class ModelRelation
    implements IteratorAggregate
{
    protected $_iterator;
    protected $_mapper;
    protected $_method;
    protected $_arguments;

    public function __construct( MapperAbstract $mapper, $method, array $arguments = array() )
    {
        $this->_mapper    = $mapper;
        $this->_method    = $method;
        $this->_arguments = $arguments;
    }

    public function getIterator()
    {
        if( $this->_iterator === null )
        {
            $this->_iterator = call_user_func_array( array( $this->_mapper, $this->_method ), $this->_arguments );
        }

        return $this->_iterator;
    }

    public function __call( $name, array $arguments )
    {        
        return call_user_func_array( array( $this->getIterator(), $name ), $arguments );
    }
}

Ben Scholzen 的实际实现 is here .

你使用它的方式是这样的:

class UserMapper
    extends MapperAbstract
{
    protected $_addressMapper;

    public function __construct( AddressMapper $addressMapper )
    {
        $this->_addressMapper = $addressMapper;
    }

    public function getUserById( $id )
    {
        $userData = $this->getUserDataSomehow();

        $user = new User( $userData );
        $user->addresses = new ModelRelation(
            $this->_addressesMapper,
            'getAddressesByUserId',
            array( $id )
        );

        return $user;
    }
}

class AddressMapper
    extends MapperAbstract
{
    public function getAddressesByUserId( $id )
    {
        $addressData = $this->getAddressDataSomehow();

        $addresses = new SomeAddressIterator( $addressData );

        return $addresses;
    }
}

$user = $userMapper->getUserById( 3 );
foreach( $user->addresses as $address ) // calls getIterator() of ModelRelation
{
    // whatever
}

事情是这样的;这可能会变得非常慢,如果对象图在某个时候变得非常复杂并且嵌套很深,因为映射器都必须查询自己的数据(假设您正在使用数据库进行持久化)。当我将此模式用于 CMS 以获取嵌套的 Pages 对象(任意深的子页面)时,我遇到了这种情况。

它可能会通过一些缓存机制进行调整,以大大加快速度。

关于php - 如何使用 Data Mapper 模式延迟加载子对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7575751/

相关文章:

php try catch报错

NHibernate - 属性延迟加载可能吗?

ruby-on-rails - 在同一个数据库上工作的多个工作线程 - 如何使其正常工作?

iphone - 核心数据是否实现了数据映射器模式?

javascript - 完全禁用 Guzzle 的重定向

php - 提示在我的网页上下载文件

php - Symfony2 在监听器中使用记录器

c# - Entity Framework Core - 延迟加载不适用于 Getters

.net - 使用函数导入进行延迟加载

ruby - 不区分大小写,例如在带有 Postgresql 的 Datamapper 中(ilike)