Skip to content
This repository was archived by the owner on Jan 30, 2020. It is now read-only.
This repository was archived by the owner on Jan 30, 2020. It is now read-only.

[RFC] Replace Input with a chain of callbacks. #87

Open
@Maks3w

Description

@Maks3w

I started to think the best way of build a custom pipe of filters and validators where you can filter after validation, etc.

I propose replace Zend\InputFilter\Input with a custom chain of methods like A+ promises.

For resume A+ promises have the following main properties along others I won't detail here:

  • has the shape of then(callback success = null, callback error = null)
  • success chain is broken when an exception is raised
  • if error chain return a value then the next success callback continue with the value provided.

So basically the chain do two kind of things. Transformations of the input value and reject the chain if is invalid.

$chain = new Chain();
$chain
  ->then(
    // Tipical filter function
    function($inputValue) use ($context) {
      return $filteredValue;
    }
  )
  ->then(
    // Tipical validation function
    function($inputValue) use ($context) {
      if ( ! isValid($inputValue) {
        throw new ValidationException(); // Break the chain
      }

      // Note MUST return a value, not the isValid boolean.
      // It can return any other object like DateTime or a database Entity
      return $inputValue;
    }
  )

  ->then($hydrate)
  ->then($validate)
  ->then($filter)

  ->then(
    null,
    function ($error) use ($context) {
      if  ($error === null) {
        // chain was invoked without `$inputValue` (i.e. optional field)
        return $fallbackValue;
      }

      throw $error;
    }
  )
  ->then(
    null,
    function ($error) use ($context) {
      // Use the fallback value when input is invalid
      return $fallbackValue ? : throw $error;
    }
  ),
  ->then(
    null,
    function ($error) use ($context) {
      // A fixed error message when input is invalid
      throw new ValidationException("fixed error message");
    }
  )
;

$context = mixed;
$chain->resolve($inputValue);

Options:

  • Reject promise using a reject method callback instead throwing exceptions.

    ->then($reject($errror) {}, $inputValue);

Benefits of this design:

  • Complete customization of the pipe.
  • Avoid create two times the same object, one for validate and another one for normalize (like DateTime)

Thoughts?

/cc @weierophinney, @Ocramius, @bakura10, @zendframework/community-review-team

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions