zendframework/zf2 — pull request #5000 by bakura10 (2013-08-21 20:21:27+00:00)
Title: [WIP] ZF3 - Hydrator refactoring

Hi everyone,

After filter and input filter components, I'm starting this PR about hydrator. As we don't have any formal discussion board for ZF3, I open PR for that (@ocramius told me to do so to). I hope it does not bother you @weierophinney.

NOTE : the code is not working yet, it's just a draft for new ideas.

## Hydrators

Like Input Filters, I think Hydrators were without any doubt the best addition to ZF2 and one of the most useful component. It would be good to see if we could discuss about it to make them even better.

There are several points where I think hydrators could be improved and where we should focus our attention: performance and clarity.

### Own namespace

First of all, I created a new namespace, Zend\Hydrator. In ZF2 it was lost inside Zend\Stdlib, but as it is an essential component, I think this is no longer correct to let it live in Stdlib namespace. Does everyone agree with that?

### Performance

When I reviewed input filter component, I realized one thing: all of those critical component has received TONS of new features since they were introduced in ZF 2.0. Hydrators received strategies, filters, class methods hydrator has gained a lot of features…

As a consequence, they are now pretty slow and contains a lot of features that often cover edge cases or very application specific problematic.

I don't know what you guys/girls are thinking about it, but I think we should make sure that those critical components stay as small and efficient as possible. I've been able to have a nearly 10x performance speed-up for input filters by rewriting them and removing some very edge-cases parts.

I'm think here about the ClassMethods hydrator. This hydrator covers now a lot of different cases, but maybe we should just make more assumptions, for example that attributes are camelCased (which is the convetnion in PHP), that getters are always prefixed by get or is, and so on… In the refactor I've started, ClassMethods now does a lot less things.

We should ask people that have specific needs to extends and create their own hydrators instead of adding features to the core hydrators. What do you think about it?

### Use of traits

Hydrators seems a good place to use traits. I now replaced the StrategyEnabledInterface and FilterEnabledInterface by two "ProvidesStrategies" and "ProvidesFilters". This way, any hydrators can quickly benefits those two features by using the traits.

Of course, all the standard hydrators use those two traits by default.

### Changes in interface

As we are allowed to BC in ZF3, I've changed the StrategyInterface interface, so that now extract and hydrate methods have a context. This was already done in ZF2.2 but the interface couldn't be changed. It's now done.

### Changes in ClassMethods

As I said, ClassMethods became really bloated. It did a lot of string manipulations, handled a lot of very specific cases, handled underscore_separated and camelCased (with string transform everywhere…). I think we should keep this hydrator very simple and make some assumptions about its usage.

I removed completely the underscore_separatd thing, so now it only assumes camelCase (it makes no sense to have getMy_Property method, and most people had to overwrite the default setting).

### New features

There are a few things that I'd like to add in hydrator component: a way to have recursive hydrators. I'm not sure yet about how to implement it yet but maybe we could do it efficiently using RecursiveIteratorIterator.

This is useful because often, an object is made of other objects, and there are a lot of cases where it is useful to also hydrate/extract the children objects.

Another case is when using a REST api : we often need to hydrate/extract values, and recursively convert an object to an array (optionally with a max depth recursion).

### Questions

While Marco and I were working on ZfrRest, we stumbled upon an interesting case: we are using hydrators a lot in REST context to take the POST data, convert it to array, hydrate an object, and at the opposite, taking an object, extract it and return the data.

Often, there is some needs of normalizing data. For instance, some JS library may return data formatted in a given way, and receive data in a very specified way too.

In a sense, the underscore_separated option in ClassMethods was trying to solve this by transforming underscore_separated keys (most likely that would come from JSON) to camelCase (another reason to remove this things from ClassMethods hydrator, I think it's not the right place).

However, we could not come with a nice solution. Do you think this is something that could fit into a Hydrator component or not at all.

### Anything else

If you have any feature requests, things you think should be removed/added, or whatever, this is the place =).