Ошибка недопустимого смещения строки PHP 5.4

#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] не будет существовать.