ddeboer / data-import

Import data from and export data to a range of different file formats and media
MIT License
567 stars 123 forks source link

[RFC] Remove array typehint from various classes to allow Traversable, ArrayAccess objects #318

Open maks-rafalko opened 7 years ago

maks-rafalko commented 7 years ago

Hi,

I would like to add a new great feature, but first of all, I will explain why

Problem

I need to filter those products (lines) from the CSV file where both Stock < 10 AND Price < 20. The key word here is AND.

So I want to have validators that can validate the array with dependent fields when both conditions must be met.

This is impossible with plain PHP arrays. Simply Symfony Validator can not do it. We can't use Expression or Callback constraints for plain PHP arrays, we can use them only with objects. (see ValidatorFilter to understand limitations of PHP arrays).

Solution

We can replace a plain PHP array with ArrayObject and use it just like a simple array, but additionally we can assign all class-based Constraints to our object and get all the power of Symfony Validator.

Let's have an example of how to correctly filter out those products with this new approach:

class ImportedProductDto extends \ArrayObject
{
    /**
     * @Assert\Callback
     */
    public function validate(ExecutionContextInterface $context, $payload)
    {
        if ($this['stock'] < 10 && $this['price'] < 20) {
            $context->buildViolation('Product has stock less than 10 AND price less than 20!')
                ->atPath('stock')
                ->addViolation();
        }
    }
}

and then in the import command:

...
$converterStep = new ConverterStep();

$converterStep->add(function (array $item) {
    // convert plain PHP array to ArrayObject
    return new ImportedProductDto($item);
});

$stepAggregator->addStep($converterStep);
...

That's it.

So since we extend the built-in ArrayObject, all the rest code works as expected because such objects can be used as arrays: $input['cost']

The only one thing is that we need to remove array typehint (or introduce iterable for PHP7.1+ later) and adopt ValidationFilter to work with this approach.

As a result, we will bring the full power of Class Constraints to this library and still can use plain PHP arrays as well as ArrayAccess objects.

What do you guys think about this RFC?

I look forward to you reply and ready to provide a PR.

@Baachi @ddeboer