はじめに
Laravelで提供されているヘルパー関数data_getの第二引数がnullだった場合の挙動が意図しないものだったので、結果と実際どのような処理が行われているかを理解するために記事をまとめます。
実証環境
PHP 7.4
Laravel 6.2
引数による結果の違い
第二引数によって、以下ような結果になります。
$characters = [
'player' => ['cuphead', 'mugman'],
'boss' => ['The Root Pack', 'Goopy Le Grande', 'Ribby and Croaks']
];
dump(data_get($characters, 'player', '第二引数のキーなし'));
// array:2 [▼
// 0 => "cuphead"
// 1 => "mugman"
// ]
dump(data_get($characters, 'mob', '第二引数のキーなし'));
// "第二引数のキーなし"
dump(data_get($characters, null, '第二引数のキーなし'));
// array:2 [▼
// "player" => array:2 [▼
// 0 => "cuphead"
// 1 => "mugman"
// ]
// "boss" => array:3 [▼
// 0 => "The Root Pack"
// 1 => "Goopy Le Grande"
// 2 => "Ribby and Croaks"
// ]
// ]
1回目のdumpは第一引数に指定した配列やオブジェクトに第二引数のキーが存在するため、その中身を返しています。2回目については、キーが存在しないため、第三引数の値を返しています。
注目するのは3回目のdumpで、第二引数をnullにしたところ配列すべてが返ってきました。デフォルトを設定していますがこちらが返ってくることはありませんでした。
実際の処理
ソースコードは以下のようになっています。
function data_get($target, $key, $default = null)
{
if (is_null($key)) {
return $target;
}
$key = is_array($key) ? $key : explode('.', $key);
while (! is_null($segment = array_shift($key))) {
if ($segment === '*') {
if ($target instanceof Collection) {
$target = $target->all();
} elseif (! is_array($target)) {
return value($default);
}
$result = [];
foreach ($target as $item) {
$result[] = data_get($item, $key);
}
return in_array('*', $key) ? Arr::collapse($result) : $result;
}
if (Arr::accessible($target) && Arr::exists($target, $segment)) {
$target = $target[$segment];
} elseif (is_object($target) && isset($target->{$segment})) {
$target = $target->{$segment};
} else {
return value($default);
}
}
return $target;
}
処理の最初で、キーがnullなら第一引数をそのままreturnしていました。
終わりに
単純な処理ではありますが、意図しない挙動があった場合はリファレンスだけではなくてソースコードの確認をすべきだと思いました。