2010-09-14 4 views
2

Я пытаюсь разобрать строку JSON с использованием PHP, JSON отправляется в файл PHP с использованием jQuery $.ajax в этом формате [{"value":"59"},{"value":"7"},{"value":"46"}], но по какой-то нечетной причине я продолжаю получать эту ошибку "Invalid argument supplied for foreach()", здесь мой PHP и JQuery код,PHP JSON parsing, дающий ошибку

JQuery:

$(".systems").each(function(i, system) { 
     // for each location block 
     system = $(system); 
     var sys = { 
      'value' : $("select[data-prod='products']", system).val() 
     }; 
     allSystems.push(sys); 
    }); 

     $.ajax({ 
       type: 'POST', 
       url: 'systems.php', 
       dataType: 'json', 
       data: { systems: JSON.stringify(allSystems), uid: uid }, 
       success: function(data){ 
        alert(data) 
       } 
     }); 

PHP:

require_once 'classes/Zend/Json.php'; 

$json = $_POST['systems']; 
$uid = $_POST['uid']; 
$array= Zend_Json::decode("$json"); 

mysql_connect('localhost','user','pass') or die(mysql_error()); 
mysql_select_db('products') or die(mysql_error()); 

//insert the suppliers products into the database 
foreach($array as $key){ 
    $query = mysql_query("INSERT INTO suppliersProducts (product_id, supplier_id) VALUES('".$key['value']."', '".$uid."') ") or die(mysql_error()); 
} 

print_r($json); 

Как вы можете видеть, я использую framewor Zend k для декодирования строки JSON, которая передается в PHP, и формат кажется мне правильным, поэтому я понятия не имею, что еще может быть причиной этой ошибки, может быть, кодирования? Есть идеи?

Thanx заранее!

+1

Попробуйте 'var_dump' на $ json, а также $ test и опубликуйте его, чтобы начать ... – Select0r

+0

Когда я делаю' var_dump' на '$ json', я получаю это ' string (19) "[{\" value \ ": \" 6 \ "}]" и на '$ test' Я получаю' NULL', теперь я использую Zend_Json :: decode() для декодирования JSON, и когда я тестирую его с помощью форматированной строки Я получаю массив, но не тогда, когда я передаю JSON поверх ajax, поэтому я предполагаю, что может быть, что передаваемый JSON не в правильном формате? – Odyss3us

+0

Точный дубликат от того же пользователя: http://stackoverflow.com/questions/3707205/php-foreach-error-invalid-argument-supplied-for-foreach – fabrik

ответ

7

Похоже, что json_decode() не смог обработать данные в этом параметре post. Добавьте к вашему скрипту некоторую обработку ошибок.

$test = json_decode($json, true); 
if (is_null($test)) { 
    die('data is not encoded as valid json'); 
} 
else if (!is_array($test)) { 
    die('Unexpected data structure. Array expected.'); 
} 

Вы также можете быть заинтересованы в json_last_error()


обновление: Может быть, это проблема кодирования. Поскольку у вас нет доступа к json_last_error(), вы можете проверить строку и кодировку «вручную», например.

if (is_null($test)) { 
    // <--- for debugging purposes only 
    echo '<pre>Debug: $json='; 
    var_dump($json); 
    echo 'hex='; 
    for($i=0; $i<strlen($json); $i++) { 
    printf('%02X ', ord($json[$i])); 
    } 
    echo '</pre>'; 
    // for debugging purposes only --> 
    die('data is not encoded as valid json'); 

Вы также должны использовать mysql_real_escape_string() при смешивании значения, как строковые литералы в инструкцию SQL, см CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')

$mysql = mysql_connect('localhost','user','password') or die(mysql_error()); 
mysql_select_db('products', $mysql) or die(mysql_error($mysql)); 

... 

$sql = " 
    INSERT INTO 
    suppliersProducts 
    (product_id, supplier_id) 
    VALUES 
    (
     '" . mysql_real_escape_string($key['value'], $mysql) . "' 
     , '" . mysql_real_escape_string($uid, $mysql) . "' 
    ) 
"; 
$query = mysql_query($sql, $mysql) or die(mysql_error($mysql)); 

Или еще лучше: использовать подготовленный, параметризованные запросы, смотрите, например, PDO - Prepared statements and stored procedures

+0

Я добавил обработку ошибок, и я получаю это: «данные i s не закодирован как действительный json », я просто поговорил с моим хостинг-провайдером, и они говорят, что они находятся на PHP версии 5.2.6, есть ли другой способ обойти это? – Odyss3us

+0

Хм, тогда у вас нет доступа к json_last_error(). Мой _guess_ есть что-то не так с кодировкой (json_decode() требует кодировки utf-8). см. обновление .... – VolkerK

0

Осмотрите значение $ test и $ json. $ json, похоже, не является JSON-Array, как указано в комментарии, поэтому $ test не станет массивом PHP.

Вы должны проверить, что $ test - это массив, прежде чем использовать его в цикле foreach.

if(is_array($test)) { 
    // proceed.. 
} 
2

Похоже $test это на самом деле не является массивом в вашем другом сервере, поэтому json_decode, вероятно, не возвращает массив. Является ли json_decode доступным даже на этом сервере? Он доступен только после php 5.2.0. Посмотрите на phpinfo() для деталей версии.

Установите error_reporting(E_ALL) и ini_set('display_errors', 1) сверху, чтобы вы не увидели ошибок перед проработкой.

+0

Сервер работает 5.2.6, но я все еще получаю эту ошибку friggin! – Odyss3us

2

Поскольку foreach() работает только на массивах, вы должны использовать is_array($test), чтобы проверить, что вы получили массив из JSON перед вызовом foreach().

0

Просто измените следующее:

$json = $_POST['systems']; 
$uid = $_POST['uid']; 
$test = json_decode($json, true); 

Для

$json = !empty($_POST['systems']) ? json_decode($_POST['systems'], true) : array(); 
$json = is_array($json) ? $json : array(); 

$uid = $_POST['uid']; 
foreach($json as $key => $value) 
{ 
    //Less error prone. 
} 
+0

Это лучше, но это все еще не указано, что $ _POST ['systems'] содержит json-массив (это переменная post, поэтому может быть что угодно), поэтому вы должны проверить is_array() перед выполнением цикла foreach. – Spudley

+0

обновлен со второй строкой для устранения проблемы с помощью json validation. – RobertPitt

0

Как уже сказал, Еогеасп() выдаст эту ошибку, если вы пытаетесь использовать его с переменной, либо не массив или не установлен вообще, поэтому, если возможно, что это может произойти, вы должны проверить с помощью is_array() перед циклом foreach.

Однако я также хотел опубликовать ответ, чтобы указать, что сообщение, которое вы видите, является только сообщением уровня предупреждения в PHP. Другими словами, ваша программа будет продолжать работать после того, как эта ошибка встретится (она пропустит цикл foreach() и продолжит работу после нее). Кроме того, можно установить PHP, используя PHP.ini, чтобы запретить отображение предупреждающих сообщений (или даже любых других сообщений об ошибках). Это возможно (например, если вы внесли изменения в свою систему или если вы используете программу в другой системе), возможно, вы все время имели ошибку, но никогда не видели ее раньше.

0

Вы проверили кодировку строки перед ее расшифровкой через Zend_Json::decode()? Это обычная проблема - если вы принуждаете формат к, например, utf8 (через utf8_encode()), это может сработать для вас.

+0

Нет, я этого не делал, я пытался форсировать кодировку, но не повезло, насколько я знаю, $ .ajax публикует данные в utf8. – Odyss3us

1
Когда я делаю var_dump на $ JSON я получаю эту строку (19) "[{\" значение \ ": \" 6 \ "}]"

Похоже magic_quotes_gpc на. Фактическая строка, закодированная json, будет [{"value":"6"}], но благодаря ужасной магической котировке все двойные кавычки заменяются на \ ", что делает ее недействительной для json_decode(). Вы можете использовать stripslashes() для« обратного повреждения ».

$json = get_magic_quotes_gpc() 
    ? stripslashes($_POST['systems']) : $_POST['systems']; 
0

Одна вещь, вы можете попробовать, когда вы объявляете свои системы в цикле .each, оберните значение в кавычки что-то вроде этого:.

var sys = { 
     'value' : "'" + $("select[data-prod='products']", system).val() + "'" 
    }; 

PHP-анализатор может потребовать значение в кавычки