Я пытаюсь получить полную строку для добавления в дружественный URL из многомерного массива PHP неопределенная глубина. Подобно тому, что делает WordPress. Результат будет как parent/son/grandson
, Вот пример массива, который у меня будет:
Array
(
[0] => Array
(
[id] => 26
[slug] => animals
[children] => Array
(
[0] => Array
(
[id] => 29
[slug] => insects
[children] => Array
(
[0] => Array
(
[id] => 32
[slug] => grasshoppers
)
)
)
[1] => Array
(
[id] => 28
[slug] => mammals
[children] => Array
(
[0] => Array
(
[id] => 30
[slug] => dogs
)
[1] => Array
(
[id] => 31
[slug] => horses
)
)
)
)
)
[1] => Array
(
[id] => 27
[slug] => minerals
[children] => Array
(
[0] => Array
(
[id] => 33
[slug] => salt
)
)
)
)
Я хотел бы вызвать функцию как:
$full_slug = getFullSlug('dogs', $array);
И содержание $ full_slug было бы:
"animals/mammals/dogs"
После некоторого исследования я нашел примеры для подобных случаев, используя array_unshift на рекурсивные методы, но я не мог прийти с чем-то работающим для этого конкретного случая самостоятельно. Любая помощь с этим маленьким getFullSlug () функция будет оценена!
Это довольно легко сделать с помощью рекурсии:
function getFullSlug($key, $array) {
foreach($array as $node) {
if($key == $node['slug']) { //Found it on this node
return $node['slug'];
}
else //Search depth first
{
if (isset($node['children']) && is_array($node['children']) && !empty($node['children']) ) {
$subSlug = getFullSlug($key, $node['children']);
if(!empty($subSlug)) //If it was found
{
return $node['slug'].'/'.$subSlug;
}
else //Look at the next sibling
{
continue;
}
} else { // This is a leaf, and it wasn't found
continue;
}
}
}
return ''; //Failed to find it.
}
Конечно, это можно добавить и к классу. Если вы сделаете это, вам нужно обновить вызов getFullSlug до $ this-> getFullSlug (….).
Вот массив slugs, который я тестировал, и который должен быть таким же, как вы упомянули:
$slugs = array(
array(
'id' => 26,
'slug' => 'animals',
'children' => array(
array(
'id' => 29,
'slug' => 'insects',
'children' => array(
array(
'id' => 32,
'slug' => 'grasshoppers'
)
)
),
array(
'id' => 28,
'slug' => 'mammals',
'children' => array(
array(
'id' => 30,
'slug' => 'dogs'
),
array(
'id' => 31,
'slug' => 'horses'
)
)
)
)
),
array(
'id' => 27,
'slug' => 'minerals',
'children' => array(
array(
'id' => 33,
'slug' => 'salt'
)
)
)
);
Наконец, вот код, использующий функцию:
echo getFullSlug('animals', $slugs).'<br>';
echo getFullSlug('insects', $slugs).'<br>';
echo getFullSlug('grasshoppers', $slugs).'<br>';
echo getFullSlug('mammals', $slugs).'<br>';
echo getFullSlug('dogs', $slugs).'<br>';
echo getFullSlug('horses', $slugs).'<br>';
echo getFullSlug('minerals', $slugs).'<br>';
echo getFullSlug('salt', $slugs).'<br>';
И соответствующий вывод, как и ожидалось:
animals
animals/insects
animals/insects/grasshoppers
animals/mammals
animals/mammals/dogs
animals/mammals/horses
minerals
minerals/salt
Надеюсь это поможет!
Постскриптум Чтобы проверить, существует ли слаг, вы можете использовать empty ().
Для примера выше,
$url = getFullSlug('platypus', $slugs);
if(empty($url))
echo "Slug doesn't exist";
else
echo "New url: $url";
вывел бы «Slug не существует», если утконос не существует в многомерном массиве $ slugs, и вывел бы что-то вроде «Новый URL: животные / млекопитающие / утконос», если бы он существовал.
Нечто подобное должно работать для вас:
public function getFullSlug($key, $array) {
foreach($array as $arrayKey => $arrayValue) {
if (is_array($arrayValue)) {
return $arrayKey . '/' . $this->getFullSlug($key, $arrayValue);
} else if ($arrayValue === $key) {
return $arrayValue;
}
throw InvalidArguementException("full slug could not be built for $key", 404);
}
}