#php
#php
Вопрос:
Я использую конструкцию foreach для просмотра массива, возвращаемого из функции. К сожалению, эта функция возвращает разные структуры, если имеется только 1 результат, чем если имеется более 1 результата. Когда есть один результат, я получаю следующее:
array(3) {
["name"]=>
string(5) "chris"
["admin"]=>
string(5) "chris"
["time"]=>
string(19) "2014/06/27 12:36:31"
}
string(34) "$1$9243ujf0i2j8ehdf24hdf9a8"
Я пытаюсь вывести значение [«name»]. Если я использую следующий код, моя переменная содержит правильные данные, но я получаю ошибку недопустимого смещения строки:
foreach($res[1]['result']['user']['entry'] as $user) {
$s = $user['name'];
echo $s;
}
Как мне правильно получить значение массива [«name»]? Или я должен сделать что-то другое на более высоком уровне? Необработанные данные, которые я получаю обратно, выглядят следующим образом, когда есть одна запись:
array(2) {
["@attributes"]=>
array(2) {
["status"]=>
string(7) "success"
["code"]=>
string(2) "19"
}
["result"]=>
array(2) {
["@attributes"]=>
array(2) {
["total-count"]=>
string(1) "1"
["count"]=>
string(1) "1"
}
["user"]=>
array(2) {
["@attributes"]=>
array(2) {
["admin"]=>
string(5) "chris"
["time"]=>
string(19) "2014/06/27 12:39:58"
}
["entry"]=>
array(2) {
["@attributes"]=>
array(3) {
["name"]=>
string(5) "chris"
["admin"]=>
string(5) "chris"
["time"]=>
string(19) "2014/06/27 12:36:31"
}
["phash"]=>
string(34) "$1$9243ujf0i2j8ehdf24hdf9a8"
}
}
}
}
и следующее, когда имеется более одной записи:
array(2) {
["@attributes"]=>
array(2) {
["status"]=>
string(7) "success"
["code"]=>
string(2) "19"
}
["result"]=>
array(2) {
["@attributes"]=>
array(2) {
["total-count"]=>
string(1) "1"
["count"]=>
string(1) "1"
}
["user"]=>
array(2) {
["@attributes"]=>
array(2) {
["admin"]=>
string(5) "chris"
["time"]=>
string(19) "2014/06/27 12:57:32"
}
["entry"]=>
array(2) {
[0]=>
array(2) {
["@attributes"]=>
array(3) {
["name"]=>
string(5) "chris"
["admin"]=>
string(5) "chris"
["time"]=>
string(19) "2014/06/27 12:36:31"
}
["phash"]=>
string(34) "$1$9243ujf0i2j8ehdf24hdf9a8"
}
[1]=>
array(2) {
["@attributes"]=>
array(3) {
["name"]=>
string(4) "test"
["admin"]=>
string(5) "chris"
["time"]=>
string(19) "2014/06/27 12:57:32"
}
["phash"]=>
string(34) "$1$as9d8jf238r9jf89j9238jr"
}
}
}
}
}
Обратите внимание на дополнительный уровень индексированного массива после [«entry»] . По сути, мне просто нужен список значений [«name»].
Комментарии:
1. Я почти уверен, что вы хотите
foreach($res[1]['result']['user']['entry']['@attributes'] as $user)
. Оба они содержатname
бит внутри этого подмассива.2. не совсем. Посмотрите на структуру еще раз, разделение происходит после вступления.
3. @Энтони: Спасибо, но это не сработает. Когда имеется более одной записи, там есть дополнительный уровень массива: $res[1][‘result’][‘user’][‘entry’][0][‘@attributes’]. Когда есть одна запись, это просто $res[1][‘result’][‘user’][‘entry’][‘@attributes’].
4. Я совершенно пропустил то место, где запись разбивается на массив. Но если вы не добавите ни к одному из путей, это приведет к незаконному смещению
@attributes
. Откуда берется массив?5. @Anthony: смотрите мой комментарий к этому ответу.lau_ ниже.
Ответ №1:
Служба, которая возвращает различную структуру в зависимости от количества результатов, изначально не работает. Если это не может быть исправлено, вы можете попытаться нормализовать данные перед их обработкой с помощью чего-то вроде этого:
if (!isset($res[1]['result']['user']['entry'][1]) {
// Not an array, so change the structure to an array with one element:
$res[1]['result']['user']['entry'] = array($res[1]['result']['user']['entry']);
}
// Now process the data as if the service is always returning an array
Комментарии:
1. Исходная функция, которая возвращает данные, преобразует некоторый XML в массив, выполняя $xml = simplexml_load_string, $json = json_encode($xml), а затем $ret_array = json_decode($json, true). Не уверен, смогу ли я это исправить или есть лучший способ сделать это. Несмотря на это, ваш ответ отлично сработал! Спасибо.
2. Изменение данных для адаптации к коду в целом не такая уж хорошая идея, но это будет «работать».
Ответ №2:
Вы могли entry
бы нормализовать массив следующим образом:
if(!isset($entries['result']['user']['entry'][0])) {
$entry_list[] = $entries['result']['user']['entry'];
} else {
$entry_list = $entries['result']['user']['entry'];
}
Затем работайте с новым $entry_list
массивом foreach
без проблем.
Комментарии:
1. Спасибо! Это привело к созданию самого простого кода, на мой взгляд.
2. это выглядит проще, но имеет тот же эффект, что и @this.lau_ с дополнительным присвоением $entry_list
Ответ №3:
Вы можете использовать is_array
$test = $res[1]['result']['user']['entry'];
if (is_array($test)) {
foreach($test as $user) {
$s = $user['@attributes']['name'];
echo $s;
}
} else {
$s = $test['@attributes']['name'];
echo $s;
}
Комментарии:
1. Похоже, это не работает. is_array($test) вычисляет значение true независимо от того, есть ли одна запись или несколько. Что мне нужно знать, я думаю, так это то, существует ли $res[1][‘result’][‘user’][‘entry’][0] или не существует.
2. Используя ваше предложение, я заставил работать следующее: $test = $res[1][‘result’][‘user’][‘entry’]; if (is_array($test[0])) { foreach($test как $user) { echo $user[‘@attributes’][‘name’]; } } else {echo $test[‘@attributes’][‘name’]; }
3. Мне просто не хватало части [‘@attributes’] … но если вы протестируете $test[0] вместо $test, вы получите ошибку, если это единственное значение, потому что $test[0] не будет существовать.