phpro / zf-doctrine-hydration-module

Configurable Doctrine hydrators for ZF2
18 stars 33 forks source link

New Feature: Provide for an Easy Way to Filter Fields #10

Closed gsomoza closed 9 years ago

gsomoza commented 9 years ago

This issue is just meant to brainstorm about the possibility of providing an easy mechanism to filter fields once #8 is merged.

I was thinking we could provide an abstract factory that would simplify the process of filtering fields for entities and making that easy to version as well (based on API version). The idea is as follows:

// module configuration
'doctrine-hydrator' => [
    'Api\\V1\\Rest\\User\\UserHydrator' => [
        // .... other config
        'filters' => [
            'user-filter' => [
                'filter' => 'Api\\V1\\Rest\\User\\UserFilter'
            ],
        ],
    ],
],

The key Api\V1\Rest\User\UserFilter can obviously have a real service behind it. But by default it would hit a new ExtractFilterFactory abstract factory that will attempt to build any class that follows the regular expression: /^BEF.*?Filter$/ (we could change this). E.g. it would build a class named Api\V1\Rest\User\UserFilter.

To tie things up, we would provide a BaseExtractFilter class off which any filters can inherit. The class would implement the filter() method and automatically exclude any fields defined in a protected property of the instanced object.

At the end of the day, from a user's point of view, it would be possible to filter extraction output by simply following the config snippet above and defining the following class:

<?php
namespace Api\V1\Rest\User;
use Phpro\DoctrineHydrationModule\Utils\BaseExtractFilter;

class UserFilter extends BaseExtractFilter {
    protected $extractWhitelist = array(
        'id', 'firstname', 'lastname' // all other fields will not be extracted
    );
} 

If this is interesting then I have almost everything ready for a PR, just need to incorporate it into your namespaces etc (its currently implemented at the project level).

veewee commented 9 years ago

A better option is to create a real PluginManager for 'Hydrator\FilterInterface', just like there are Pluginmanagers for Zend\Filter, ... Maybe the official repository of Zend Framework 2 is a better place to introduce this new PluginManager.

Configuration would look something like:

return [
    'hydrator_filiters' => [
        'invokables' => [
            'Namespace\Hydrator\Filter\WhitelistFilter' => 'Namespace\Hydrator\Filter\WhitelistFilter',
        ],
        'aliases' => [
            'whitelist' => 'Namespace\Hydrator\Filter\WhitelistFilter',
        ],
    ],
    'doctrine-hydrator' => [
        'Api\\V1\\Rest\\User\\UserHydrator' => [
            // .... other config
            'filters' => [
                'user-filter' => [
                    'filter' => 'whitelist',
                    'options' => [
                        'whitelist' => ['id', 'firstname', 'lastname'],
                    ]
                ],
            ],
        ],
    ],
];

Instead of loading the hydration filters from the real serviceManager, they will be loaded from the PluginManager like this:

<?php
/** @var \Zend\ServiceManager\AbstractPluginManager hydratorFilterManager */
$hydratorFilterManager = $serviceManager->get('HydratorFilterManager');
$filter = $hydratorFilterManager->get('whitelist', [
    'whitelist' => ['id', 'firstname', 'lastname']
]);

(This also makes it easier to create real abstract factories.)

gsomoza commented 9 years ago

Great, thanks for the advice. Will look into building that and introducing it to the official ZF2 repo or any other repo interested in providing this (e.g. I think this could be of special interest to Apigility users).