Retry with Exponential Backoff
Automatically retry failed operations with increasing delays and jitter to prevent thundering herd problems.
Access deeply nested array values using dot notation with graceful fallback on missing keys.
function arrayGet(array $data, string $path, mixed $default = null): mixed
{
$keys = explode('.', $path);
foreach ($keys as $key) {
if (!is_array($data) || !array_key_exists($key, $data)) {
return $default;
}
$data = $data[$key];
}
return $data;
}
Let us trace what happens when you access a deeply nested value that may or may not exist:
$data = ['user' => ['address' => ['city' => 'Austin']]];
arrayGet($data, 'user.address.city')
→ Split path: ['user', 'address', 'city']
→ Key 'user': exists → drill into ['address' => ['city' => 'Austin']]
→ Key 'address': exists → drill into ['city' => 'Austin']
→ Key 'city': exists → return 'Austin'
arrayGet($data, 'user.phone.area_code', 'unknown')
→ Split path: ['user', 'phone', 'area_code']
→ Key 'user': exists → drill into ['address' => [...]]
→ Key 'phone': does NOT exist → return 'unknown'
Without safe access (crashes on missing keys):
$city = $data['user']['address']['city'];
// TypeError if any level is missing
With isset chains (verbose and brittle):
$city = isset($data['user']['address']['city'])
? $data['user']['address']['city']
: null;
With arrayGet (clean and safe):
$city = arrayGet($data, 'user.address.city');
$code = arrayGet($data, 'user.phone.area_code', 'N/A');
// ETL: safely extract fields from inconsistent source data
$record = fetchFromApi('/customers/123');
$customer = [
'name' => arrayGet($record, 'data.attributes.name', ''),
'email' => arrayGet($record, 'data.attributes.contact.email'),
'tier' => arrayGet($record, 'data.meta.tier', 'standard'),
'city' => arrayGet($record, 'data.attributes.address.city', 'Unknown'),
];
// No try/catch needed. No isset chains. No crashes on missing fields.
Especially useful in ETL pipelines where source data is inconsistent. API responses change, optional fields appear and disappear, and nested structures vary between records. This function handles all of that with a single, readable call.