Arr::except
Returns a copy of an array with the given keys removed, including nested dot-notation keys.
public static function except($array, $keys)- Added in Laravel 5.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$$array | array | The array to filter. It is passed by value and is not modified. |
$$keys | array|string|int|float | One key or a list of keys to remove. Dot notation is supported for nested keys. |
Return value
arrayA copy of the array with the given keys removed.
Arr::except is the non-mutating sibling of Arr::forget: it copies the array, removes the listed keys from the copy, and returns it. Because it delegates to Arr::forget, everything that method understands works here too, including dot notation for nested keys.
When to reach for it
Use it whenever an array must leave your control minus a few fields: stripping password and password_confirmation before writing a request to the log, removing internal bookkeeping keys before returning a payload, or dropping a computed field before passing attributes to a model. It pairs naturally with Arr::only when you want the opposite policy.
What trips people up
Keys are matched exactly, not by pattern — there is no wildcard, so removing items.*.cost does nothing and you have to loop. Removing a key that is not present is a silent no-op rather than an error, which is convenient but means a typo is invisible. Finally, only the levels named in the key are touched: removing product.cost leaves the product array in place even if it becomes empty.
Example
When to use it
- Stripping password fields from request data before it reaches a log.
- Removing internal keys such as _token or _method before persisting a payload.
- Dropping a computed attribute before handing an array to a model factory.
Frequently asked questions
What is the difference between Arr::except and Arr::forget?
Arr::except returns a modified copy and leaves the original alone, while Arr::forget mutates the array you pass by reference and returns nothing.
Does Arr::except support wildcards?
No, keys are matched literally, so a pattern such as items.*.cost removes nothing. Build the concrete dotted keys in a loop and pass them as an array.
Does Arr::except throw if a key does not exist?
No, missing keys are ignored silently, which also means a misspelled key produces no warning of any kind.
More examples
Sanitising data before logging
Every listed key, flat or nested, is stripped from the copy handed to the logger while $payload itself is unchanged and can still be used by the rest of the handler. This snippet needs a booted application for the request and the Log facade; the Arr::except call works anywhere.
<?php
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
$payload = $request->all();
Log::info('checkout submitted', Arr::except($payload, [
'password',
'password_confirmation',
'card.number',
'card.cvc',
]));No wildcards: loop instead
The first line prints the array unchanged because 'lines.*.cost' is treated as a literal path that does not exist. The second prints {"lines":[{"sku":"A1"},{"sku":"B2"}]} after expanding the wildcard into real indexes, which is the only way to remove a key from every row.
<?php
use Illuminate\Support\Arr;
$order = ['lines' => [['sku' => 'A1', 'cost' => 4], ['sku' => 'B2', 'cost' => 9]]];
// This does nothing.
echo json_encode(Arr::except($order, 'lines.*.cost')), "\n";
// Build the concrete keys yourself.
$keys = array_map(fn ($i) => "lines.$i.cost", array_keys($order['lines']));
echo json_encode(Arr::except($order, $keys)), "\n";Removing a key leaves its parent behind
Prints {"meta":[]} then bool(true). Only the named leaf is removed, so the now-empty parent survives — and because an empty PHP array encodes as a JSON array rather than an object, the shape of your JSON changes. Remove the parent instead if an empty branch is not acceptable.
<?php
use Illuminate\Support\Arr;
$data = ['meta' => ['debug' => true]];
$clean = Arr::except($data, 'meta.debug');
echo json_encode($clean), "\n";
var_dump(array_key_exists('meta', $clean));
Discussion