Вопрос о реализации PHP - ORM Lazy Load / Identity Map - PullRequest
4 голосов
/ 28 сентября 2010

У меня есть пустая реализация ORM, состоящая из картографических данных, которые загружают и сохраняют сущности. Каждый преобразователь внутренне управляет картой идентичности для всех объектов, считанных из базы данных, так что один и тот же объект загружается в память только один раз.

В настоящее время я реализую отложенную загрузку для связанных сущностей, используя прокси-класс, который загружает связанные данные только при обращении к свойству сущности. Моя проблема в том, что прокси-класс не является самой сущностью и используется только в том случае, если сущность загружается косвенно (через отношения). Таким образом, любая === проверка, сравнивающая фактическую сущность с прокси, который загружает ту же сущность, возвращает false. Моя цель состоит в том, чтобы и сущности, и клиентский код не знали о прокси-объектах.

Прокси-класс выглядит примерно так:

class EntityProxy
{
    protected $_entity;
    protected $_loader;

    public function __construct(EntityProxyLoader $loader)
    {
        $this->_loader = $loader;
    }

    protected function _load()
    {
        if (null === $this->_entity)
        {
            $this->_entity = $this->_loader->load();
            unset($this->_loader);
        }
    }

    public function __get($name)
    {
        $this->_load();
        return $this->_entity->$name;
    }

    public function __set($name, $value)
    {
        $this->_load();
        $this->_entity->$name = $value;
    }
}

А картографы выглядят примерно так:

class PersonEntityMapper
{
    // Find by primary key
    public function find($id)
    {
        if ($this->inIdentityMap($id)
        {
            return $this->loadFromIdentityMap($id);
        }

        $data = ...;  // gets the data

        $person = new Person($data);

        // Proxy placeholder for a related entity. Assume the loader is
        // supplied the information it needs in order to load the related 
        // entity.
        $person->Address = new EntityProxy(new EntityProxyLoader(...));

        $this->addToIdentityMap($id, $person);

        return $person;
    }
}

class AddressEntityMapper
{
    // Find by primary key
    public function find($id)
    {
        ...

        $address = new AddressEntity($data);

        $address->Person = new EntityProxy(new EntityProxyLoader(...));

        $this->addToIdentityMap($id, $address);

        return $address;
    }
}

Если я загружаю запись «PersonEntity», имеющую связанный «AddressEntity», затем загружаю эту же запись «AddressEntity» напрямую через «AddressEntityMapper» и сравниваю два объекта, они не будут одинаковыми (так как один прокси, который делегирует). Есть ли способ переопределить встроенное в PHP сравнение объектов? Какие-нибудь предложения по лучшему способу справиться с этим без введения кода с поддержкой прокси в сущности и / или клиентский код?

Кроме того, я знаю, что было бы в моих интересах принять существующую и установленную ORM, но есть различные проблемы, которые мешают мне сделать это.

Ответы [ 2 ]

2 голосов
/ 28 сентября 2010

Обычный метод - создать метод equals, как в Java. PHP не позволяет вам переопределить == или ===, и я никогда не находил способ переопределить компараторы, но раньше я ошибался, и было бы здорово, если бы я ошибался в этом.

0 голосов
/ 08 февраля 2012

Не уверен в вашей проблеме, но я думаю, что сравнение должно быть сделано с использованием интерфейсов, и вместо == или === вы должны использовать if($User instanceof UserInterface)

Смотри: http://www.davegardner.me.uk/blog/tag/lazy-load/

...