Open hexus opened 9 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.
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.
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 Mapper
s 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?
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
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:
PropertyStrategy
- Set properties directlyGetterSetterStrategy
- One getter/setter method per propertyMethodStrategy
- Pass all attributes to a single methodHydratorStrategy
- Use a hydration libraryThis should probably be part of an EntityMap
, and consequently used by a Mapper
.
Pull out model & relation loading and saving from
Record
to aMapper
class that works in the same way.This means the
Mapper
will access storage, and theRecord
will access theMapper
; 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 aMapper
for eachEntity
(and perhaps anEntityMap
). Basically, Analogue but using storage interfaces instead of PDO.