Arr::set

Writes a value into a nested array using dot notation, creating any missing levels.

Signature
public static function set(&$array, $key, $value)

Parameters

ParameterTypeDescription
$&$arrayarrayThe array to write into. Passed by reference and modified in place.
$$keystring|int|nullDot-notation path to write. Passing null replaces the entire array with $value.
$$valuemixedThe value to store at the path.

Return value

arrayThe array level that was written to — the whole array for a single-segment key, the innermost level for a dot path.

Errors

Raises an error if the first argument is not a variable, since it is taken by reference.

Arr::set walks a dot path and assigns at the end of it, creating each intermediate level as an empty array when it is missing. It is the write counterpart to Arr::get.

When to reach for it

  • Assembling a deeply nested config or API request body without writing nested literals.
  • Applying a flat list of path => value overrides onto a nested defaults array.
  • Patching one field deep inside a decoded JSON document before re-encoding it.

What trips people up

Non-array values in the path are destroyed without warning. The intermediate check is ! isset($array[$key]) || ! is_array($array[$key]), so setting 'cache.driver' when cache currently holds the string 'redis' throws that string away and replaces it with an array. This is the number one surprise.

A null key replaces everything. Arr::set($array, null, $value) assigns $value over the whole array — easy to trigger accidentally when the key comes from a variable that turned out to be null.

The return value is not the whole array. Because the function rebinds its reference as it descends, a multi-segment key returns only the innermost level. Read the mutated variable you passed in; do not use the return value as the result.

There is no way to escape a literal dot in a key — every dot is a level separator.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Build a nested request payload from flat form field names.
  • Apply dot-keyed overrides onto a nested defaults array in a loop.
  • Patch a single deep field in a decoded JSON document before re-encoding.

Frequently asked questions

Does Arr::set create missing intermediate arrays?

Yes. Any segment of the path that is missing, or that holds a non-array value, is replaced with a new empty array as the function descends.

Why did Arr::set wipe out my existing value?

Because a non-array value standing in the middle of the path is overwritten with an array. Check the type at that level with Arr::get before writing through it.

Can I use a key that contains a literal dot?

No. Every dot is treated as a level separator and there is no escape syntax, so assign such keys directly with $array['a.b'] = $value.

More examples

The return value is the inner level, not the array

The first print_r shows ['c' => 1] — only the innermost level — while the variable passed by reference holds the full structure. Because the shape of the return value depends on the path depth, always read the array you passed in.

Example · php
<?php

use Illuminate\Support\Arr;

$array = [];

// Multi-segment key: the return value is the deepest level only.
$returned = Arr::set($array, 'a.b.c', 1);

print_r($returned);
print_r($array);

// Single-segment key: the return value happens to be the whole array.
$flat = [];
$returnedFlat = Arr::set($flat, 'name', 'Desk');

print_r($returnedFlat);

/*
Array
(
    [c] => 1
)
Array
(
    [a] => Array
        (
            [b] => Array
                (
                    [c] => 1
                )

        )

)
Array
(
    [name] => Desk
)
*/

Expanding flat overrides onto defaults

Existing sibling keys such as mail.from.address are untouched, while the third override builds two levels that did not exist at all. This loop is the whole implementation of a dot-keyed override system.

Example · php
<?php

use Illuminate\Support\Arr;

$config = [
    'mail' => ['driver' => 'log', 'from' => ['name' => 'Example', 'address' => '[email protected]']],
    'queue' => ['default' => 'sync'],
];

$overrides = [
    'mail.driver' => 'smtp',
    'mail.from.name' => 'Support',
    'queue.connections.redis.queue' => 'default',
];

foreach ($overrides as $path => $value) {
    Arr::set($config, $path, $value);
}

echo json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES), PHP_EOL;

/*
{
    "mail": {
        "driver": "smtp",
        "from": {
            "name": "Support",
            "address": "[email protected]"
        }
    },
    "queue": {
        "default": "sync",
        "connections": {
            "redis": {
                "queue": "default"
            }
        }
    }
}
*/

Discussion

  • Be the first to comment on this lesson.