noj / dot
Nested array/object access through dot notation
Installs: 9 733
Dependents: 1
Suggesters: 0
Security: 0
Stars: 3
Watchers: 3
Forks: 0
Open Issues: 0
Requires
- php: ^7.0|^8.0
Requires (Dev)
- phpunit/phpunit: ^6.5|^7.5
README
Dot allows you to get & set array keys or object properties using dot notation.
Installing
composer require noj/dot
Usage
First construct a new Dot instance:
$dot = new Dot($data); $dot = Dot::from($data); // alternative
All the examples are using the following data structure unless otherwise specified:
$data = [ 'groups' => [ (object)[ 'name' => 'group1', 'items' => [ [ 'name' => 'item1', 'rare' => false, ], [ 'name' => 'item3', 'rare' => true, ], ] ], (object)[ 'name' => 'group2', 'items' => [] ], (object)[ 'name' => 'group3', 'items' => [ [ 'name' => 'item2', 'rare' => true, ], ] ], ] ];
Methods
Dot::count(string $path): int
Count the number of items at a given path.
$dot->count('groups.0.items'); // 2 $dot->count('groups.*.items'); // 3
Dot::find(string $path, mixed $equals): Dot
Find items that pass the given truth test.
// find where property === value $dot->find('groups.*.items.*.rare', true)->get(); /* [ ['name' => 'item3', 'rare' => true], ['name' => 'item2', 'rare' => true], ] */ // pass a callback for custom comparisons $dot->find('groups.*.items.*.name', function (string $name) { return $name === 'item2' || $name === 'item3'; })->get(); // returns same as above // leave off the property to receive the whole item $dot->find('groups.*.items.*', function (array $item) { return $item['name'] === 'item3' && $item['rare']; })->get();
Dot::first(string $path, mixed $equals): Dot
Find the first item that passes the given truth test.
$dot->first('groups.*.items.*.rare', true)->get(); // ['name' => 'item3', 'rare' => true] $dot->first('groups.*.items.*', function (array $item) { return $item['rare'] === true; })->get(); // same as above
Dot::get(null|int|string $path): mixed
Access nested array keys and object properties using dot syntax:
$dot->get('groups.0.items.1.name'); // 'item3'
Dot safely returns null if the key or property doesn't exist:
$dot->get('groups.3.items.1.name'); // null
You can use a wildcard *
to pluck values from multiple paths:
$dot->get('groups.*.items.*.name'); // ['item1', 'item3', 'item2'] $dot->get('groups.*.items'); /* [ ['name' => 'item1', 'rare' => false], ['name' => 'item3', 'rare' => true], ['name' => 'item2', 'rare' => true], ] */
You can call functions using the @
prefix:
$data = [ 'foo' => new class { public function getBar() { return ['bar' => 'value']; } } ]; (new Dot($data))->get('foo.@getBar.bar'); // 'value'
If no argument is passed it will return the underlying data:
$dot->get() === $data; // true
Dot::has(string $path): bool
Returns true if path exists, false otherwise:
$dot->has('groups.0.items.1.name'); // true
Dot::push(string $path, mixed $value): Dot
Push a value onto an existing array:
$dot->push('groups.0.items', ['name' => 'another item']); // supports wildcards $dot->push('groups.*.items', ['name' => 'another item']);
Dot::set(array|string $paths, mixed $value): void
You can set nested values using the same syntax:
$dot->set('groups.2.items.0.name', 'a different name'); echo $data['groups'][2]->items[0]['name']; // 'a different name'
Set nested keys from multiple paths using a wildcard *
:
$dot->set('groups.*.items.*.name', 'set all to same name');
Keys will be created if they don't already exist:
$dot->set('groups.0.items.2.name', 'a new item');
By default, set will initialise missing values as empty arrays. To indicate that something should be an object use the ->
delimiter:
$dot->set('groups.3->items.2.name', 'a new item');
You can set multiple values at once by passing an array:
$dot->set([ 'groups.0.items.1.name' => 'something', 'groups.2.items.0.name' => 'something else', ]):
You can call a method:
$data = [ 'foo' => new class { public $bars = []; public function addBar($bar) { $this->bar[] = $bar; } } ]; $dot = new Dot($data); $dot->set('foo.@addBar', 'value'); echo $data['foo']->bars; // ['value']
Or call a method for each value of an array:
$dot->set('foo.@addBar*', ['value1', 'value2']); echo $data['foo']->bars; // ['value1', 'value2']
Non-chained versions
All methods have non-chained versions of themselves as a standalone function, i.e:
// instead of $filtered = \Noj\Dot\Dot::from($data) ->find('groups.*.items.*.rare', true) ->get(); // you can do $filtered = \Noj\Dot\find($data, 'groups.*.items.*.rare', true');