Ошибка: Warning: Illegal string offset как разобрать?
Есть Массив:
$_admin_left_menu =
Array(
array(
"section_name" => "Контент1",
array(
"name" => "Контент",
"link" => "/news/",
"icon" => "default"
),
array(
"name" => "Контент",
"link" => "/news/",
"icon" => "default"
)
),
array(
"section_name" => "Контент2",
array(
"name" => "Контент",
"link" => "/news3/",
"icon" => "default"
)
)
);
Далее я вывожу через foreach только "section_name" следующим кодом:
foreach ($_admin_left_menu as $section_value) {
echo $section_value['section_name'] . "<br>";
}
На выходе я получаю (Контент1 и Контент2).
Далее вывожу с этого же массва например "link" следующим кодом:
foreach ($_admin_left_menu as $section_value) {
echo $section_value['section_name'] . "<br>";
foreach ($section_value as $value) {
echo $value['link'] . "<br>";
}
}
Данные выводит, но в добавок получаю это Illegal string offset 'name' in и �.
Такую стуктуру массива использую для меню, так будет легче с ним работать, и данные я вводу вручную.
Почитав понял что нужно обращться к таким строчкам через номер массива... $value[0] и данного предупреждения нет! Но � остался.
Конечноже не удобно использовать номер массива а испрользовать индекс массива напрмиер так ['section_name'].
Хотелось бы узнать более подробней как могу придти к требуемому результату? Ведь удобней так echo $value['section_name']; писать чем echo $value[0];
PHP Version 7.3.15
Ответы (2 шт):
У вас проблема не в версии php, а неверной структуре данных.
$_admin_left_menu = [
[
"section_name" => "Контент1",
"links" => [
[
"name" => "Контент",
"link" => "/news/",
"icon" => "default"
],
[
"name" => "Контент",
"link" => "/news/",
"icon" => "default"
],
]
],
[
"section_name" => "Контент2",
"links" => [
[
"name" => "Контент",
"link" => "/news3/",
"icon" => "default"
],
]
],
];
Соответственно цикл получаем таким:
foreach ($_admin_left_menu as $section_value) {
echo $section_value['section_name'] . "<br>";
foreach ($section_value['links'] as $value) {
echo $value['link'] . "<br>";
}
}
Да и такой подход с мега-массивом не совсем уместен. Правильнее было бы обернуть всё это в классы. Как минимум в Section и Link.
UPD
class Section {
/** @var string */
private $name;
/** @var Link[] */
private $links;
public __construct($name, array $links) {
$this->name = $name;
$this->links = $links;
}
}
class Link {
private $name;
private $url;
private $icon;
public __construct($name, $url, $icon) {
$this->name = $name;
$this->url= $url;
$this->icon = $icon;
}
}
Как пользоваться, думаю, разберётесь. Геттеры и сеттеры нужные добавите под себя
Тут уже дали великолепный ответ, как лучше сделать, чтобы всё правильно работало. Дополню это объяснением, почему не работал Ваш первоначальный вариант. Думаю, это будет полезно. Вот Ваш код:
foreach ($_admin_left_menu as $section_value) {
echo $section_value['section_name'] . "<br>";
foreach ($section_value as $value) {
echo $value['link'] . "<br>";
}
}
Строка echo $section_value['section_name'] . "<br>"; сработает правильно, поскольку массив $_admin_left_menu состоит из 2 массивов ($_admin_left_menu[0] и $_admin_left_menu[1]) и каждый из этих массивов содержит элемент с индексом 'section_name'.
Но вот в Вашем внутреннем foreach начинают твориться тёмные дела. Foreach проходит по массиву $section_value и в каждом его элементе ищет вложенный элемент c индексом 'link'. Посмотрим на массив $_admin_left_menu[0] (далее будем обращаться к нему как к $section_value):
array(
"section_name" => "Контент1",
array(
"name" => "Контент",
"link" => "/news/",
"icon" => "default"
),
array(
"name" => "Контент",
"link" => "/news/",
"icon" => "default"
)
)
Он состоит из 3 элементов. Первый имеет индекс "section_name". Второму и третьему элементам Вы не задали индексы в явном виде. Поэтому PHP присвоил им числовые индексы. (Если ключ для элемента массива не указан явно, PHP использует в качестве ключа предыдущее наибольшее значение ключа типа integer, увеличенное на 1. Если Вы явно задавали элементам строковые индексы, а потом добавили в массив элемент без явно указанного индекса, PHP присвоит ему индекс 0). Элементы $section_value[0] и $section_value[1] сами являются массивами, и каждый из них содержит элемент с индексом 'link'. Для них Ваш код отработает правильно. А вот элемент $section_value['section_name'] - не является массивом. Это строка "Контент1". Но Ваш внутренний foreach всё равно попытается извлечь из него элемент с индексом 'link'. Это приведёт к ошибке, поскольку индексом в строке может быть только число.
Обращение $value[0] действительно уберёт ошибку, но Вы получите совсем не то, что хотели. Элемент с индексом 0 у Вас есть только в строках "Контент1" и "Контент2". Оттуда его и выведет в виде кракозябра (посимвольно русские буквы нормально не выводятся). Если Вы замените "Контент1" и "Контент2" на "Content1" и "Content2" соответственно, то Вы увидите, что вместо кракозябра будет напечатана буква 'C'.