views:

28

answers:

1

Hi all, I have a bare bones ORM implementation, consisting of data mappers which load and persist entities. Each mapper internally manages an identity map for all entities read from the database, so that the same entity is only loaded into memory once.

I am currently implementing lazy loading for related entities using a proxy class that loads the related data only when a property on the entity is accessed. My problem is that the proxy class is not the entity itself and is only used if the entity is loaded indirectly (via a relationship). So any === check comparing the actual entity with a proxy that loads the same entity will return false. My goal is to keep both the entities and client code unaware of the proxy objects.

The proxy class looks something like:

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;
    }
}

And the mappers look something like:

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;
    }
}

If I load a "PersonEntity" record that has a related "AddressEntity", then load that same "AddressEntity" record directly via the "AddressEntityMapper" and compare the two objects, they will not be the same (as one is a proxy that delegates). Is there any way to override PHP's built in object comparison? Any suggestions on a better way to handle this without introducing proxy aware code into the entities and/or client code?

Also, I am aware that it would be in my benefit to adopt an existing and established ORM, but there are various issues that prevent me from doing so.

+2  A: 

Usual method is to create an equals method like you would do in Java. PHP doesn't allow you to override == or === and I've never found a way to override comparators but I've been wrong before and it would be cool if I was wrong about this.

Chuck Vose
Indeed, there is no way to override `==` or `===` (and loads of other operators), so a method is the only way. It would be nice indeed if it became possible.
Wrikken
That's what I was afraid of, thanks for the answer.
rr