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

Array Undot Laravel Package

divineomega/array_undot

array_undot expands dot-notation keys back into nested PHP arrays, the inverse of Laravel’s array_dot helper. Turn ['user.name' => 'Jane'] into ['user' => ['name' => 'Jane']] for configs, form data, and validation. Lightweight with a simple API.

View on GitHub
Deep Wiki
Context7

Getting Started

array_undot is a single-purpose, framework-agnostic helper: it takes a flat array with dot-notation keys and expands it into a nested multi-dimensional array. It is the inverse of Laravel's array_dot() (and PHP's Arr::dot()).

Install:

composer require divineomega/array_undot

Requires Composer and a supported PHP version (check composer.json — the package is tiny and pinned to a modern PHP range). There is no service provider, no config file, and nothing to register in Laravel's config/app.php. The global function is loaded via Composer's files autoload, so require 'vendor/autoload.php' is all you need.

First use case — round-tripping a flattened config:

use DivineOmega\ArrayUndot\ArrayUndot;

$flat = [
    'database.connections.mysql.host'     => '127.0.0.1',
    'database.connections.mysql.port'     => 3306,
    'database.connections.mysql.database' => 'app',
];

$nested = array_undot($flat);
// or, if you prefer to avoid the global function:
$nested = ArrayUndot::undot($flat);

// [
//   'database' => [
//     'connections' => [
//       'mysql' => ['host' => '127.0.0.1', 'port' => 3306, 'database' => 'app'],
//     ],
//   ],
// ]

Where to look first: the README and the one class in src/. There is essentially no API surface beyond undot() — read the source before relying on edge-case behaviour, because that is where the real specification lives.

Implementation Patterns

1. Persist flattened config, rehydrate on read. The most common use: store settings in a single flat table/column with dot keys, then expand at boot.

$settings = Settings::pluck('value', 'key')->all(); // dotted keys
config(['app' => array_undot($settings)]);

2. Layer user overrides on top of defaults. Undot the override set first, then merge structurally — plain array_merge on dotted keys gives you the wrong result.

$merged = array_replace_recursive($defaults, array_undot($overrides));

3. Rebuilding payloads from form fields. Browsers and JSON-flattening tools happily send addresses.0.city / user.profile.bio. Undot gives you a request-shaped array.

$payload = array_undot($request->only(['name', 'addresses.0.city', 'addresses.0.zip']));

4. Database rows as paths. Rows of (path, value) — CMS page settings, feature flags, translation keys — map cleanly onto undot.

$tree = array_undot($rows->pluck('value', 'path')->all());

5. Cache round-trip. Flatten a big nested config with array_dot() before writing to Redis, array_undot() after reading. Keeps the cached format flat and greppable.

6. Wrap it, don't scatter it. Because it is a bare global function, define a thin service (ConfigExpander::expand(array $flat): array) around it in larger codebases. You get one seam to swap in a custom implementation, add validation, or log malformed input.

Integration tips:

  • In Laravel, call it freely — there is no facade to import, and the global function is always available via autoload.
  • For queue jobs and API resources, expand as early as possible (at the boundary) and pass structured arrays around internally.
  • Pair it with data_get()/Arr::get() on the read side so the nesting depth stays an implementation detail.

Gotchas and Tips

Conflicting keys are order-dependent. If the input contains both a parent and a child path, one silently wins:

array_undot(['a' => 1, 'a.b' => 2]); // 'a' becomes an array; scalar 1 is lost

Nothing warns you. If your input can contain both (e.g. a settings table with a "group default" row and per-key rows), filter or sort deterministically before calling.

Literal dots in keys cannot be escaped. A key that genuinely contains a . — a domain name, a file extension, a version string — will be split. array_dot() has the mirror problem, so it is not a bug in this package, but it will bite you on keys you don't control (user-defined translation keys, metric names).

Numeric segments need verification. Whether 'items.0.name' produces ['items' => [0 => ['name' => ...]]] (int key) or ['items' => ['0' => ...]] (string key) matters for assertEquals vs assertSame and for json_encode output. Check the source and pin it with a test; PHP's loose array-key coercion helps, but strict comparisons won't.

The round-trip is not always lossless. array_dot() on an empty nested array produces nothing, so array_undot(array_dot($x)) can drop empty branches. Don't use the pair to assert "unchanged data" in tests without accounting for that.

Trailing / leading dots. 'a.b.' or '.a' will create odd empty-string segments rather than throwing. Validate key format upstream if input is user-supplied.

No config, no extension points. There is nothing to publish, no separator option, no escaping strategy, no callback hook. If you need any of that, don't try to configure the package — write your own 20-line undot (or wrap this one and pre-process the keys). Given the LGPL-3.0 licence, vendoring/reimplementing for a closed-source product is worth a conversation with legal rather than an assumption.

Global function name collision. If another dependency also defines array_undot(), Composer's autoload order decides which one wins, and the failure is a fatal redeclare. Prefer ArrayUndot::undot() in libraries; use the global function only in application code.

Debugging. The fastest loop is dd(array_undot($flat)) on a two-key subset. To verify a suspected lossy round-trip, diff array_dot(array_undot($flat)) against your original $flat — the keys that disappear are your conflicts or empty branches.

Small package, low activity (24 stars). The upside: it is ~100 lines and easy to audit. The downside: no maintenance guarantees, sparse docs, edge cases documented only by the tests. Write a handful of characterization tests around the specific inputs your app produces (numeric keys, conflicting paths, dotted literals) so a future PHP or package change surfaces loudly instead of corrupting nested config at runtime.

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.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle