consolidation/filter-via-dot-access-data
Filter nested PHP arrays with concise dot-access paths. This lightweight package lets you query config-like data using readable dotted keys, simplifying conditional filtering and value lookup in Laravel or plain PHP projects without verbose array access. Ideal for configuration, request data, and ne...
This is a tiny, single-purpose package: it wraps dflydev/dot-access-data so CLI apps can accept a dot-notation path (for example user.profile.name) and return only the matching subset of a nested array. The public surface is essentially one class, Consolidation\Filter\Filter, plus the filter() method.
Minimal setup:
composer require consolidation/filter-via-dot-access-data
Where to look first:
vendor/consolidation/filter-via-dot-access-data/src/Filter.php — this is the whole implementation.vendor/dflydev/dot-access-data/ — useful if you only need to extract a single value instead of a filtered structure.First use case — let users narrow JSON output from a command:
use Consolidation\Filter\Filter;
$data = [
'user' => [
'name' => 'Ada Lovelace',
'email' => '[email protected]',
],
'meta' => ['request_id' => 'abc123'],
];
$filtered = (new Filter())->filter($data, 'user.email');
// [
// 'user' => ['email' => '[email protected]'],
// ]
The result is normally a structure-preserving subset of the input, not a scalar. If you need just the scalar value, use dflydev/dot-access-data directly:
use Dflydev\DotAccessData\Data;
$name = (new Data($data))->get('user.name'); // "Ada Lovelace"
Input should be a plain nested array. Decode JSON with json_decode($json, true) rather than leaving objects as stdClass.
Symfony Console command option. Add a --filter option, apply it before serializing:
protected function configure(): void
{
$this->addOption(
'filter',
null,
InputOption::VALUE_REQUIRED,
'Dot-path filter, e.g. user.profile.name'
);
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$data = $this->getExportData();
if ($path = $input->getOption('filter')) {
$data = (new Filter())->filter($data, $path);
}
$output->writeln(json_encode($data, JSON_PRETTY_PRINT));
return self::SUCCESS;
}
Laravel / Artisan. The package has no service provider, so register it once and inject it:
// AppServiceProvider::register()
$this->app->singleton(\Consolidation\Filter\Filter::class, fn () => new \Consolidation\Filter\Filter());
public function handle(\Consolidation\Filter\Filter $filter): int
{
$data = $this->buildReport();
if ($path = $this->option('filter')) {
$data = $filter->filter($data, $path);
}
$this->line(json_encode($data, JSON_PRETTY_PRINT));
return self::SUCCESS;
}
Filter before formatting, never after. If you use consolidation/output-formatters, JSON/YAML serializers, or table renderers, filter the array first and then format. Once data has been converted into a table or rendered string, the dot-path filter can no longer traverse it.
Multiple selections. If your version accepts multiple paths, pass them consistently rather than parsing in the command:
$filtered = $filter->filter($data, [
'user.name',
'user.email',
'meta.request_id',
]);
If it accepts a comma-separated string instead, centralize that parsing in a small wrapper so call sites stay clean.
Normalize models to arrays. Eloquent models, DTOs, and API responses often contain objects. Convert recursively before filtering:
$array = json_decode(json_encode($model), true);
$filtered = (new Filter())->filter($array, 'user.profile');
Wrap the dependency. Because the package is small and unmaintained, isolate it behind your own service:
namespace App\Support;
use Consolidation\Filter\Filter;
class OutputFilter
{
public function __construct(private Filter $filter) {}
public function apply(array $data, ?string $path): array
{
if ($path === null || $path === '') {
return $data;
}
return $this->filter->filter($data, $path);
}
}
This gives you one place to swap in a custom implementation or a maintained fork.
Testing pattern. Add a data provider around the paths your CLI documents:
yield 'nested scalar' => [
['user' => ['name' => 'Ada', 'email' => '[email protected]']],
'user.name',
['user' => ['name' => 'Ada']],
];
NOASSERTION; inspect the LICENSE file in the repository before distributing or vendoring. Do not assume MIT.vendor/consolidation/filter-via-dot-access-data/composer.json. Older packages often constrain PHP to ^5.x or ^7.x; installation can fail on PHP 8.x. Prefer widening the constraint in a fork over --ignore-platform-reqs, which hides real compatibility problems.dflydev/dot-access-data traverses arrays. JSON decoded as objects (json_decode($json)) or DTOs will not filter as expected. Always normalize to associative arrays first.example.com) or file names (report.pdf) are interpreted as nested paths. There is no standard escaping mechanism; rename keys in your output or filter from a shallower level.items.0.name and items.*.name may behave differently. Wildcard handling is the most likely place for surprises, so test every documented path form against real fixture data.null. Normalize and decide whether your command should print {} or exit with a helpful error.Dflydev\DotAccessData\Data::get() directly.--filter= with no value. Decide whether empty means “no filtering” or “invalid input” and enforce it explicitly.--fields=name,email style flattening is a different operation. Pick one convention per command and document it, or users will mix them.db.password, internal.token) if the source array contains them. Allowlist top-level keys before applying the filter, or filter a pre-sanitized export.var_dump((new \Consolidation\Filter\Filter())->filter($fixture, $path));
Then codify each supported path form in a unit test. Because the implementation is only a few files, reading Filter.php once is usually faster than debugging through trial and error.
How can I help you explore Laravel packages today?