pharaonic/php-dot-array
Pharaonic PHP Dot Array gives you clean dot-notation access to nested arrays: get, set, has, and forget values like config('app.name') for any array. Lightweight, framework-agnostic, and easy to drop into Laravel or plain PHP projects.
Install with Composer and confirm the entry point before writing any code — the package is small enough that the README plus src/ is the whole API surface.
composer require pharaonic/php-dot-array
use Pharaonic\DotArray\DotArray; // confirm namespace/class in src/
$config = [
'database' => [
'connections' => [
'mysql' => ['host' => '127.0.0.1', 'port' => 3306],
],
],
];
DotArray::get($config, 'database.connections.mysql.host'); // '127.0.0.1'
DotArray::get($config, 'database.connections.pgsql.host', 'localhost'); // default
Where to look first
get, set, has, forget, and whether wildcards apply to each) are actually implemented versus aspirational.src/ — this is a single-class library; read the whole thing in five minutes. Pay attention to whether methods are static, instance-based, or both, and whether mutators return a new array or operate by reference.tests/ — the fastest way to learn wildcard edge cases (ordering, empty matches, nested *).First use case: replacing chains of isset($a['b']['c']) ? $a['b']['c'] : $default in config loaders, API response parsing, and settings bags. If you are on Laravel, you already have Illuminate\Support\Arr; reach for this package when you are writing framework-agnostic code or a standalone package where pulling in illuminate/support is disproportionate.
Config reader with defaults. The highest-value pattern is a thin read layer with sane fallbacks, so callers stop doing null checks:
final class Config
{
public function __construct(private array $values) {}
public function get(string $path, mixed $default = null): mixed
{
return DotArray::get($this->values, $path, $default);
}
}
Keeping the package behind your own Config/Settings class means a future swap to Arr or adbar/array-reader is a one-file change.
Progressive array building. Use dotted set to construct deeply nested output from flat input — handy for normalizing form payloads or mapping flat env vars into a nested structure:
$out = [];
DotArray::set($out, 'mail.from.address', '[email protected]');
DotArray::set($out, 'mail.from.name', 'Example');
Feature flags / settings bags. Store a flat associative array, read with dot paths, and use has for existence checks before branching. This avoids ?? pyramids and keeps the flag file one-dimensional at rest.
Wildcard extraction for collections. The wildcard support is the differentiator over hand-rolled explode('.') helpers. Typical use: pulling one column out of a decoded JSON list.
$payload = ['users' => [
['id' => 1, 'email' => '[email protected]'],
['id' => 2, 'email' => '[email protected]'],
]];
DotArray::get($payload, 'users.*.email'); // ['[email protected]', '[email protected]']
Wrap this in a small pluck() helper on your own class so callers do not depend on the wildcard syntax directly — that keeps the escape hatch available if wildcard semantics change.
Cleanup with forget. When sanitizing user-submitted structured data (e.g. removing password_confirmation from a nested DTO), forget on a dotted path is clearer than recursive unset loops. Verify first whether it reindexes numeric arrays, since that affects JSON output shape.
Boundary discipline. Pass arrays by value into the library, get arrays back out, and store the result. Do not let dotted paths leak into public APIs, database columns, or templates — keep them an internal addressing convention.
app.name or v1.2 is indistinguishable from a path separator. Check whether the package supports escaping (backslash, bracket syntax, or an explicit "literal" mode). If not, flatten those keys before storing or accept that they are unreachable by dot path.get to support * while set and forget do not, or to behave differently on a wildcard that matches nothing (empty array vs null vs no-op). Test each of the four operations with: no match, single match, multiple matches, and a * in the middle of a path.set returns a new array rather than mutating by reference, code like DotArray::set($a, 'x.y', 1); followed by reading $a silently does nothing. This is the single most common source of "it works in the test, not in the app" bugs with dot-array libraries.has versus isset semantics. A path whose value is null may report as present under one and absent under the other. Decide which you need for your use case and write a one-line test to pin the behavior; do not assume parity with Laravel's Arr::has.forget on items.0 may leave a hole ([1 => ...]) which json_encode renders as an object instead of an array. Run array_values() on the result if the output must stay a JSON array.get($arr, 'a.b', null) is the signature, you cannot distinguish "missing" from "explicitly null". Use has first when that distinction matters.set/forget with an attacker-controlled path lets them write or delete arbitrary structure in the array you pass in. Whitelist keys or validate against a schema.'items.01' vs 'items.1') may or may not resolve to the same element under PHP's array key coercion. Test if your data uses zero-padded keys.array_map over the collection. This is not a concern for config reads; it is for per-row processing.composer.json ("pharaonic/php-dot-array": "1.0.*" or the specific tag), and keep the wrapper class described above so an exit is cheap. Read the source before upgrading.$payload['users']) rather than re-running the dotted call — wildcard expansion failures are almost always a shape mismatch one level up, not a library bug.How can I help you explore Laravel packages today?