darya / framework

PHP Web Application Framework
http://darya.io/
MIT License
2 stars 1 forks source link

Data Mappers #17

Open hexus opened 9 years ago

hexus commented 9 years ago

Pull out model & relation loading and saving from Record to a Mapper class that works in the same way.

This means the Mapper will access storage, and the Record will access the Mapper; another layer if you will.

This makes Active Record pattern optional, and the Data Mapper pattern what everything hinges on. It separates the concerns and means users won't have to extend Record to make use of relation loading, but if they do extend it then their relations can just be loaded in exactly the same way.

This one might take a bit of working out. Ultimately: class/method extraction yo!

Edit: EntityManager that contains a set of mappers and their relationships. Basically the Data Mapper pattern that Active Record can optionally sit on top of.

Edit edit: EntityManager that holds a Mapper for each Entity (and perhaps an EntityMap). Basically, Analogue but using storage interfaces instead of PDO.

hexus commented 6 years ago

The GenericRepository would actually just be a Mapper to a Storage interface.

Think Analogue, but with that extra layer of storage abstraction instead of assuming SQL.

hexus commented 6 years ago

Could start by introducing Mapper, whose constructor takes an Entity class and/or instance and maps basic methods, like ->query().

Then, an EntityMap could be extracted from Entity, and Mapper's constructor would take them both, plus a Storage interface (#47) . Mapper's API wouldn't change other than the constructor, and the implementation would change according to the extraction.

hexus commented 6 years ago

An initial layout for this has been implemented, and it looks good!

Fleshing this out involves porting the relationships and having them depend on related entity maps and mappers, rather than entities.

It would also be fab to have a Manager like class so we can do this:

$orm->mapper(MyEntity::class);

And register Mappers like this:

$orm->setDefaultStorage($databaseStorage);
$orm->register(MyEntity::class, MyEntityMap::class);
$orm->register(OtherEntity::class, OtherEntityMap::class, $fileStorage);

And after that, making it possible to skip providing an entity class altogether. A map and a storage is all that's really needed.

Mapping the same entity to different storage interfaces will need to be thought about further. Should this be done at the mapper level, at the storage level, or either?

hexus commented 6 years ago

Mappers need their own Query class, that could decorate any Storage\Query, so that methods like ->with() and ->has() can be used to load relationships

hexus commented 5 years ago

Use the strategy pattern to implement mapping strategies for different kinds of entity classes. Entities shouldn't be forced to implement an interface to be mappable.

Example strategies:

This should probably be part of an EntityMap, and consequently used by a Mapper.