Level-2 / Maphper

Maphper - A php ORM using the Data Mapper pattern
BSD 2-Clause "Simplified" License
52 stars 7 forks source link

Declarative schema and anisomorphic object-table mappings #22

Open LexLythius opened 9 years ago

LexLythius commented 9 years ago

I'm not sure whether this falls within the intended scope of Maphper, but here it is.

Configuration allowing, Database will attemp to create columns as needed whenever a property doesn't have an identically named column in the DB table. This is pretty handy in some cases, but it would be good to have a way to map props to columns arbitrarily.

Sometimes you change your model but can't/won't rename table fields (happens every now and then with non-exclusive DBs); sometimes your DB doesn't handle column renaming gracefully; sometimes you're able to alter a table but you rather wouldn't (last I checked, MySQL took a fair amount of time to re-structure existing tables with large row counts).

Also, some DBs are less forgiving than MySQL when accepting inputs (i.e., UPDATE table SET count = '1' ... fails with some of them), in which case metadata becomes necessary in order to validate/massage client input prior to statement execution).

Prop-to-column mappings should be fairly easy: $options['mappings'] = [ 'prop' => 'col_name', ... ]

Col metadata would result in something like: $options['fields'] = [ 'col_name' => [ 'type' => ..., 'length' => ..., ...] ... ]

In both cases, there are at least two approaches: 1) declarative, client-driven schema through config files in some sensible format (PHP, YAML, JSON; I share your aversion of PHP's docblock pseudo-annotations). 2) DB introspection, which could or could not result in turn in config files being generated.

What do you think?

TRPB commented 9 years ago

This is a good idea. It's not currently implemented but I did begin to implement an option for only loading specific columns for a table and lazy loading others (like BLOB columns) this makes sense as an enhancement.

I don't want to use Introspection as I don't want to tie Maphper to specific databases/data sources. Instead, my goal with Maphper is to have Maphper generate the database from its config rather than generating its config from the database. This way you can just swap out mysql for a csv file and maphper will just create the relative structure for either.

Your idea of specifying the column mappings in the options makes sense, however I can foresee a this may cause a couple of issues if you're remapping the primary key column(s), although I think they should be able to be worked around.

edit: That said, there's no reason Maphper couldn't generate config from the DB. It could even work out relationships base on foreign keys, although I'd probably release this as a separate optional extra, maybe even CLI app as ideally it wouldn't need to be run often and wouldn't ever be included on each page load.