Вот такой говнокод нахрапом, но нужно добавить везде проверки:
$tree = $array1;
$array = $array2;
//вытаскивает значения из массива с детьми, и если место куда вставить ребёнка не нашлось, помещает его в конец
//Внимание! Функция войдёт в рекурсию, если места для ребёнка не найдётся - этот момент нужно фиксить
function one(array &$tree, array &$array) {
//if (empty($array)) return false;
$search = array_shift($array);
$temp = $tree;
$tree = two($tree, $search);
if (serialize($tree) == serialize($temp)) $array[] = $search;
if (!empty($array)) one($tree, $array);
}
//ищет куда вставить детей
function two(array $array, array $search) {
$tree = [];
foreach($array as $key => $value) {
$tree[$key] = $value;
if ($value['page'] == $search['referer']) {
$tree[$key]['childs'][] = $search;
} elseif (!empty($value['childs'])) {
$tree[$key]['childs'] = two($array[$key]['childs'], $search);
}
}
return $tree;
}
one($tree, $array);
var_dump($tree);