Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laminas Inputfilter Laravel Package

laminas/laminas-inputfilter

Laminas InputFilter provides a robust, extensible system for filtering and validating input data in PHP applications, with composable filter and validator chains, nested input handling, and error reporting for reliable form and API data processing.

Deep Wiki
Context7

Getting Started

Install the package and let Composer pull in its siblings (laminas-filter, laminas-validator, laminas-servicemanager):

composer require laminas/laminas-inputfilter

The mental model is small and consistent: an InputFilter is a named collection of Input objects. Each Input owns a filter chain (normalization) and a validator chain (assertions). Filters run first, then validators, and only after isValid() do you read getValues().

First use case — validating a registration or API payload:

use Laminas\Filter\StringTrim;
use Laminas\InputFilter\InputFilter;
use Laminas\Validator\EmailAddress;
use Laminas\Validator\StringLength;

$filter = new InputFilter();

$filter->add([
    'name'       => 'email',
    'required'   => true,
    'filters'    => [['name' => StringTrim::class]],
    'validators' => [['name' => EmailAddress::class]],
]);

$filter->add([
    'name'       => 'password',
    'required'   => true,
    'validators' => [
        ['name' => StringLength::class, 'options' => ['min' => 12]],
    ],
]);

$filter->setData($requestData);

if (! $filter->isValid()) {
    // ['email' => ['emailAddressInvalid' => '...'], ...]
    $errors = $filter->getMessages();
} else {
    $clean = $filter->getValues(); // filtered, unknown keys stripped
}

Where to look first: src/InputFilter.php, src/Input.php, src/Factory.php, src/CollectionInputFilter.php, and src/FileInput.php. Then read docs/book/ for the spec-array format; the tests are the best reference for edge-case behavior around emptiness and chains.

Implementation Patterns

Prefer spec arrays over fluent add() calls. Specs are portable, diffable, and can live in configuration or be reused between HTTP, CLI, and queue workers. Factory::createInputFilter() builds nested filters, collections, and file inputs recursively:

$factory = new \Laminas\InputFilter\Factory();

$filter = $factory->createInputFilter([
    'email' => [
        'required'   => true,
        'filters'    => [['name' => \Laminas\Filter\StringTrim::class]],
        'validators' => [['name' => \Laminas\Validator\EmailAddress::class]],
    ],
    'profile' => [
        'type'         => \Laminas\InputFilter\InputFilter::class,
        'input_filter' => [
            'display_name' => ['required' => true],
            'bio'          => ['required' => false],
        ],
    ],
]);

Wrap reusable filters in classes. For anything used in more than one endpoint, subclass InputFilter or implement InputFilterAwareInterface; for laminas-form/entity wiring, implement InputFilterProviderInterface::getInputFilterSpecification(). This keeps controller code to setData() / isValid() / getValues().

Resolve from the container where the framework integration exists. In laminas-mvc, spec arrays under the input_filter_specs config key are retrievable via the InputFilterManager. In Mezzio/standalone, pull InputFilterPluginManager from the container or invoke Factory directly with specs kept in your own config. Register custom filters and validators through the filters/validators plugin configuration and reference them by FQCN to avoid alias drift.

Use validation groups for partial updates. PATCH endpoints should not require the full payload:

$filter->setValidationGroup(['email']);           // top-level only
$filter->setValidationGroup(['profile' => ['bio']]); // nested group

Express cross-field rules with Callback, not filters. Callback validators receive the whole raw context as a second argument, which is the right place for "state is required when country is US" style logic.

Use CollectionInputFilter for repeated rows. Attach a row-level input filter, feed it the array of rows, and set an explicit count when cardinality is contractual (e.g. exactly three addresses); otherwise let it derive from the data. Validate file uploads with FileInput plus Laminas\Validator\File\UploadFile, MimeType, Extension, and Size, then move the file yourself from getValue()['tmp_name'].

Treat the input filter as the normalization boundary. Do trimming, ToInt, boolean coercion, and empty-to-null conversion in filters so services and repositories only ever see getValues(). One filter per endpoint/command, reused across HTTP and CLI, is usually the sweet spot.

Gotchas and Tips

  • Filters run before validators, including the emptiness check. A whitespace-only string plus StringTrim becomes '' and can then fail required — even though the raw value looked present. Order filters deliberately.
  • required, allow_empty, and continue_if_empty are the number-one source of confusion. Required means "must be present"; allow_empty => false means "if present, must not be empty"; continue_if_empty => true means "still run validators on empty values." That last one is useful for optional fields with a format rule, but the validator will happily fail on '', so guard it with a Callback or accept the failure deliberately.
  • Know what counts as empty. '', null, and [] are treated as empty. JSON null and a missing key are not always semantically the same; decide per field and test it.
  • getValues() is only meaningful after isValid(). It returns filtered values and silently strips unknown keys. Use getRawValues() for debugging, never for persistence.
  • Messages are nested arrays keyed first by input name, then by validator message key. Flatten them with a small recursive helper before returning a 422 payload; don't hand the raw structure to an API consumer.
  • Plugin resolution happens at configuration time. Unknown filter/validator names throw during setup, not during validation, which is good — but it means a typo in a rarely used branch can fail the whole container build. Prefer FQCNs over legacy short names (StringTrim, Int, etc.).
  • Tune chain breaks for performance. break_chain_on_failure per validator and break_on_failure per input save cycles on large payloads, but they hide additional messages. Enable them only when you don't need a full error report.
  • CollectionInputFilter cardinality is easy to get wrong. Set setCount() when the count is part of the contract; otherwise verify against your data shape rather than assuming it is inferred.
  • FileInput is a validator, not an uploader. It validates $_FILES-shaped arrays and holds the metadata; you still need move_uploaded_file() and explicit UPLOAD_ERR_* handling.
  • setData() requires an array or Traversable. Decode PSR-7 JSON bodies first and reject malformed JSON before the filter sees it, otherwise you get an InvalidArgumentException instead of a validation error.
  • Debugging recipe: dump getRawValues(), then getValues(), then getMessages(). If a value appears "missing," check whether a filter converted it to '' or whether required/allow_empty short-circuited the validators.
  • Version awareness: OptionalInputFilter and newer filter class names (e.g. ToInt) are recent additions. Pin the package version and favor FQCNs over legacy aliases to keep upgrades boring.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource