Unpack json in php - php

I am trying to unpack my json object send via http post request in a php controller:
$products = $_POST['products'] ?? '';
foreach($products as $purchase){
$productId =$purchase['productid'];
$qty = $purchase['quantity'];
$params = array(
'form_key' => $this->formKey->getFormKey(),
'product' => $productId,
'qty' => $qty
);
//Load the product based on productID
$_product = $this->product->load($productId);
$this->cart->addProduct($_product, $params);
$this->cart->save();
}
This is the format of my json object being sent, stored in a variable called list.
0: {productid: "2910", quantity: "2"}
1: {productid: "2911", quantity: "1"}
2: {productid: "2913", quantity: "4"}
3: {productid: "2914", quantity: "3"}
This is my post request (content type is also set to application/json):
$.post("http://dev.website.co.uk/batchorder/index/addtocart",
{
products:list,
},
function(data, status){
console.log("Data: " + data);
console.log("Status: " + status);
});
This has always worked for me before so i cannot see where i am going wrong with it.
The error i am getting is Warning: Invalid argument supplied for foreach(). but i am assuming it has something to do with my json object.
EDIT:
$("#AddToCartButton").click(function(){
var list = [];
$("#tabCollection :input").each(function(){
var input = $(this);
if($(this)[0].value > 0){
var myArray = {'productid': $(this)[0].id, 'quantity': $(this)[0].value};
list.push(myArray);
}
});
var JSONStringlist = JSON.stringify(list);
var JSONlist = JSON.parse(JSONStringlist);
console.log(JSONlist);
$.ajaxSetup({
headers:{
'Content-Type': "application/json",
}
});
$.post("http://dev.website.co.uk/batchorder/index/addtocart",
{
"products":JSONlist,
},
function(data, status){
console.log("Data: " + data);
console.log("Status: " + status);
});
});
EDIT 2:
example of JSON String:
[{"productid":"2182","quantity":"1"},{"productid":"2183","quantity":"1"},{"productid":"2184","quantity":"1"},{"productid":"2185","quantity":"1"}]

$products = $_POST['products'] ?? '';
foreach($products as $purchase){
Your $products is either "something that is iterable" or a empty string.
In case it's a array, it's iterable, and the foreach will succesfully execute. But in case it's a empty string, it's going to complain about "Warning: Invalid argument supplied for foreach()", cause a string is not really iterable.
So what you need to do is make sure, that $products is always an array, either an empty or filled with json objects.
If you change:
$products = $_POST['products'] ?? '';
to:
$products = json_decode($_POST['products']) ?? array();
The foreach won't complain, and if $_POST['products'] is empty nothing will be saved in the cart.
In your javascript file change:
$.post("http://dev.website.co.uk/batchorder/index/addtocart",
{
"products":JSONlist,
},
function(data, status){
console.log("Data: " + data);
console.log("Status: " + status);
});
});
to:
$.post("http://dev.website.co.uk/batchorder/index/addtocart",
{
"products":JSONStringlist,
},
function(data, status){
console.log("Data: " + data);
console.log("Status: " + status);
});
});
You are parsing an JavaScript object to JSON, and then you're reparsing it back to an JavaScript object.
PHP does not really understand JavaScript objects, but understands JSON objects.

Related

Why do I have invalid argument supply for foreach in Laravel for json response? [duplicate]

This question already has answers here:
Invalid argument supplied for foreach()
(20 answers)
Reference - What does this error mean in PHP?
(38 answers)
Closed 10 months ago.
I am working on Razorpay integration and after succesful payment when I try to save the details to the database I get an error. I am sending the details through AJAX and in controller when I try to use foreach and look in console I always get the error invalid argument supplied for foreach statement.
this is the script after successful transaction
<script>
function demoSuccessHandler(transaction) {
// You can write success code here. If you want to store some data in database.
$("#paymentDetail").removeAttr('style');
$('#paymentID').text(transaction.razorpay_payment_id);
var paymentDate = new Date();
$('#paymentDate').text(
padStart(paymentDate.getDate()) + '.' + padStart(paymentDate.getMonth() + 1) + '.' + paymentDate.getFullYear() + ' ' + padStart(paymentDate.getHours()) + ':' + padStart(paymentDate.getMinutes())
);
$.ajax({
method: 'post',
url: "{!!route('dopayment')!!}",
dataType:"json",
data: {
"_token": "{{ csrf_token() }}",
"product": "{{ json_encode($product)}}",
"Company": "{{ $company}}",
"Address": "{{$address}}",
"Contact": "{{$contact}}",
"razorpay_payment_id": transaction.razorpay_payment_id
},
complete: function (r) {
console.log('complete');
console.log(r);
}
})
}
</script>
<script>
var options = {
key: "{{ env('RAZORPAY_KEY') }}",
amount: '{{ $subtotal}}',
name: 'AMCOR RAZORPAY',
description: 'AMCOR INTERNATIONAL',
image: 'https://i.imgur.com/n5tjHFD.png',
handler: demoSuccessHandler
}
</script>
the controller function is
public function dopayment(Request $request) {
$input = $request->all();
$product = $request->product;
foreach ($product as $single) {
# code...
print_r($single->name);
}
print_r($product);
exit;
}
You may decode product string before loop through it
//...
$product = json_decode($request->product, true);
//...
Please Json Decode before foreach loop
public function dopayment(Request $request) {
$input = $request->all();
$product = json_decode($request->product);
foreach ($product as $single) {
# code...
print_r($single->name);
}
print_r($product);
exit;
}
The error occurs because $product returns a single value instead of an array; a check will work in this case.
if (is_array($product ) || is_object($product ))
{
foreach($product as $arrayItems){
// Perform x.
}
}

Display JSON Data in HTML using Laravel 4

Please help me with my problem in displaying JSON data into my view..
my script is:
$('#supplierId').change(function(){
$.get("{{ url('api/dropdown')}}",
{ option: $(this).val() },
function(data) {
var firstnameID = $('#firstnameID');
$.each(data, function(index, element) {
firstnameID.val(element.first_name);
});
});
});
and my JSON reply is:
{"id":7,"first_name":"John","last_name":"Doe"}
the thing is when i tried to:
alert(element.first_name);
it says UNDEFINED, but when I:
alert(element);
it gives me the value of the last name which is Doe.. my question is how can I then access the other values like the ID and the first name..
EDITED:
this is my route:
Route::get('api/dropdown', function(){
$input = Input::get('option');
$supllier = Supplier::find($input);
returnResponse::json($supllier->select(array('id','first_name','last_name'))
->find($input));
});
Please help me with this one, This is my first time using JSON so im a bit confuse on how this works.
Best Regards
-Melvn
Why are you using each? This should work:
$('#supplierId').change(function(){
$.get("{{ url('api/dropdown')}}",
{ option: $(this).val() },
function(data) {
var firstnameID = $('#firstnameID');
firstnameID.val(data.first_name);
});
});
Ok, give this a try..
Explicitly state that what you're expecting back from the server is JSON using the dataType option in get().
$('#supplierId').change(function()
{
$.get("{{ url('api/dropdown')}}",
{ option: $(this).val() },
function(data)
{
var firstnameID = $('#firstnameID');
$.each(data, function(index, element)
{
firstnameID.val(element.first_name);
});
},
'json' // <<< this is the dataType
);
});
Now you should be able to access the data using the dot syntax:
console.log("last_name: " + element.last_name);
console.log("first_name: " + element.first_name);
console.log("id: " + element.id);
I would add another few lines, just to check that you're getting back what you expect to see:
console.log("NEW ELEMENT"); // << indicator in the console for your reference
console.log(element); // << the whole "element"

$.getJSON seems to return as literal string with nested objects

Hello I am new to JSON and have run into some issues.
I am requesting some information using jquery's $.getJSON method like so:
function getPlayerPositions(type) { //left/top/move
var loadUrl = "../php/client_communication/relay_positions.php";
var playerPos = [];
$.ajaxSetup ({
cache: false,
async: false
});
$.getJSON( loadUrl, { type: type } )
.done(function( data ) {
useReturnData(data);
})
.fail(function( jqxhr, textStatus, error ) {
var err = textStatus + ', ' + error;
console.log( "Request Failed: " + err);
});
function useReturnData(data){
playerPos = data;
alert("response: "+playerPos);
};
//reset to asynchronous ajax from now on
$.ajaxSetup ({
async: true
});
alert(playerPos[0]);
return playerPos;
}
And when my function is ran previously to this time I receive the correct JSON encoded data that I can then access via my "playerPos" array. (ie. alert(playerPos[4]))
But this time I am receiving data that contains multiple nested objects:
This is the ajax response alerted:
response: [{"Position":"LB","ID":" 2","x-offset":" 0","y-offset":" 0","Stats":{"ID":"2","IMG":"/images/player_avatars/player_test.png","First_Name":"Daniel","Surname":"Vernall","Nickname":"Tall Tree","number":"25","Fav_Pos_1":"LB","Fav_Pos_2":"CB","team":"A","SPEED":"100","AGILITY":"100","STRENGTH":"100","JUMP":"100","MARKING":"100","STAMINA":"100","LEADERSHIP":"100","ADAPTABILITY":"100","RESTRAINT":"100","INJURY_PRONE":"100","HEAL_TIME":"100","MORALE":"100","AGGRESSIVENESS":"100","PASSING":"100","SHOOTING_ACCURACY":"100","SHOOTING_POWER":"100","HEADING":"100","MISC_BODY":"100","POSITIONING":"100","FIRST_TOUCH":"100","LONG_DISTANCE":"100","STRONG_FOOT":"0","CONTROL":"100","CURLING":"100","CHIPPING":"100","VOLLEYING":"100","SET_PIECES":"100","THROW_INS":"100","REFLEXES":"100","ONE_ON_ONES":"100","AERIAL_ABILITY":"100","CATCHING":"100","COORDINATION":"100","THROWING":"100","coordX":0,"coordY":0,"yellowCards":0,"redCards":0,"shotsOnTarget":0,"shotsOffTarget":0,"goals":0,"assists":0,"completedPasses":0,"incompletePasses":0,"tackles":0,"timesTackled":0,"intercepts":0,"intercepted":0,"badReceive":0}},{"Position":"LCB","ID":" 3","x-offset":" 0","y-offset":" 0","Stats":{"ID":"3","IMG":"/images/player_avatars/player_test.png","First_Name":"Teddy","Surname":"Vernall","Nickname":"Bear","number":"11","Fav_Pos_1":"ST","Fav_Pos_2":"CAM","team":"A","SPEED":"100","AGILITY":"100","STRENGTH":"100","JUMP":"100","MARKING":"100","STAMINA":"100","LEADERSHIP":"100","ADAPTABILITY":"100","REST...,"SET_PIECES":"100","THROW_INS":"100","REFLEXES":"100","ONE_ON_ONES":"100","AERIAL_ABILITY":"100","CATCHING":"100","COORDINATION":"100","THROWING":"100","coordX":0,"coordY":0,"yellowCards":0,"redCards":0,"shotsOnTarget":0,"shotsOffTarget":0,"goals":0,"assists":0,"completedPasses":0,"incompletePasses":0,"tackles":0,"timesTackled":0,"intercepts":0,"intercepted":0,"badReceive":0}},{"Position":"GK","ID":" 12","x-offset":" 0","y-offset":" 0","Stats":{"ID":"12","IMG":"/images/player_avatars/player_test.png","First_Name":"Rumple","Surname":"Stiltskin","Nickname":"Rumpy Pump Stink","number":"29","Fav_Pos_1":"CDM","Fav_Pos_2":"LB","team":"A","SPEED":"100","AGILITY":"100","STRENGTH":"100","JUMP":"100","MARKING":"100","STAMINA":"100","LEADERSHIP":"100","ADAPTABILITY":"100","RESTRAINT":"100","INJURY_PRONE":"100","HEAL_TIME":"100","MORALE":"100","AGGRESSIVENESS":"100","PASSING":"100","SHOOTING_ACCURACY":"100","SHOOTING_POWER":"100","HEADING":"100","MISC_BODY":"100","POSITIONING":"100","FIRST_TOUCH":"100","LONG_DISTANCE":"100","STRONG_FOOT":"50","CONTROL":"100","CURLING":"100","CHIPPING":"100","VOLLEYING":"100","SET_PIECES":"100","THROW_INS":"100","REFLEXES":"100","ONE_ON_ONES":"100","AERIAL_ABILITY":"100","CATCHING":"100","COORDINATION":"100","THROWING":"100","coordX":0,"coordY":0,"yellowCards":0,"redCards":0,"shotsOnTarget":0,"shotsOffTarget":0,"goals":0,"assists":0,"completedPasses":0,"incompletePasses":0,"tackles":0,"timesTackled":0,"intercepts":0,"intercepted":0,"badReceive":0}}]
Javascript seems to not view these as individual objects:
When alerting playerPos[4] for example it will simply alert the 4th character in the string above.
I realise the above is very difficult to read but I wanted to show you an actual copy of the alert.
This is the bit from the php file it accesses:
if($type=="db_request"){
$team = new Team;
$team = $team->buildTeam(101, 'A');
ChromePhp::log($team);
$response = json_encode($team);
}
And my log above looks like this:
So you can see that the php file views "$team" as containing multiple nested objects
Any ideas?
Seems like you're double-encoding the object (with something like echo json_encode($response);). jQuery would then parse the JSON-encoded string to the JSON-encoded object string…
You can check for such serverside failure by inspecting the effective HTTP response in your browser's network inspector (Chrome devtools, Opera Dragonfly, Firebug).
"Stats":{
"ID":"3",
"IMG":"/images/player_avatars/player_test.png",
"First_Name":"Teddy",
"Surname":"Vernall",
"Nickname":"Bear",
"number":"11",
"Fav_Pos_1":"ST",
"Fav_Pos_2":"CAM",
"team":"A",
"SPEED":"100",
"AGILITY":"100",
"STRENGTH":"100",
"JUMP":"100",
"MARKING":"100",
"STAMINA":"100",
"LEADERSHIP":"100",
"ADAPTABILITY":"100",
"REST...,"SET_PIECES":"100",
"THROW_INS":"100",
"REFLEXES":"100",
"ONE_ON_ONES":"100",
"AERIAL_ABILITY":"100",
"CATCHING":"100",
"COORDINATION":"100",
"THROWING":"100",
"coordX":0,
"coordY":0,
"yellowCards":0,
"redCards":0,
"shotsOnTarget":0,
"shotsOffTarget":0,
"goals":0,
"assists":0,
"completedPasses":0,
"incompletePasses":0,
"tackles":0,
"timesTackled":0,
"intercepts":0,
"intercepted":0,
"badReceive":0
}
see the SyntaxError: Unexpected token S
Your SET_PIECES has broken out of the json making it invalid.
I know this is already answered but I noticed a few performance tips that may help quiet a bit. Avoiding nested functions when at all possible really can help speed up the application.
function getPlayerPositions(type) { //left/top/move
var loadUrl = "../php/client_communication/relay_positions.php";
var playerPos = [];
$.ajax( loadUrl, { type: type, async: false, cache: false, dataType: "json" } )
.done(function( data ) {
playerPos = data;
alert("response: "+playerPos);
})
.fail(function( jqxhr, textStatus, error ) {
var err = textStatus + ', ' + error;
console.log( "Request Failed: " + err);
});
alert(playerPos[0]);
return playerPos;
}
More info here

Getting key => value from json array passed from php

I am trying to get an array from PHP and to manipulate it further using jQuery. In my PHP file i do echo json_encode($data) and when i put an alert in my response in jQuery i get:
[
{
"CustomerID": "C43242421",
"UserID": "432421421",
"Customer": "rqewrqwreeqwr",
"Add1": "rqwerqwreqwrqwrqwr",
"Add2": " ",
"Add3": " ",
"Phone": "4131231",
"Fax": "532442141",
"Contact": "reqwrqwrw",
"Email": "gfdgdsg",
"PaymentTerm": null,
"Country": "3231",
"City": "111",
"Zip": " "
}
]
, wich is a valid json array. Now what i try to do further is get the pairs as key => value as i would in an associative array in php.
$.post("templates/test.php",
{data: query,
cond: $(this).text(),
action: 'select'
},
function(res) {
alert(res) //outputs what i pasted above
$.each($.parseJSON(res), function(key, value) {
alert(key + value);
//this outputs: 0[object Object]
});
Removing the $.parseJSON in the above function gives me a invalid 'in' operand e on jquery.min.js(line 3) in Firebug error log.Can you assist me with my troubles?
Try:
var r = $.parseJSON(res);
$.each(r[0], function(key, value) {
alert(key + value);
});
The result of $.parseJSON(res) is an array, containing a single element (an object). When you iterate over that array (using $.each), value represents the entire object that's stored at the current index of the array. You'll need to iterate over that object to output its properties:
$.each($.parseJSON(res)[0], function(key, value) {
alert(key + ' = ' + value);
});
If you have an array with multiple objects inside it, this more general code should output the key-value pairs for all of them:
$.each($.parseJSON(res), function(index, arrayObject) {
$.each(arrayObject, function(key, value) {
alert(key + ' = ' + value);
});
});
res = $.parseJSON(res);
for (var i = 0; l = res.length; i < l; i++) {
data = res[i];
customer = data.Customer;
}
You have there an Array of Objects. You can iterate through the array of objects just like the code above.
You can get some kind of object from json:
function parse_json(res)
{
try{
return eval('(' + response + ')');
}
catch(e){
// invalid json
}
}
Try this:
$.getJSON('your-json-string-file.php', function (data) {
$.each(data, function(key, val) {
alert(key +'=>'+ val)
});
});
Hope this will help you

How to send array of JSON objects with jQuery

I'm programming an web page and I really stucked trying to send an Array of JSON objects to my PHP backend script.
this is my javascript code (using jQuery):
var toSend = new Array();
$("input[type=checkbox]").each(
function (indice, item)
{
var dom = $(item);
var domJSON = {
id: dom.attr("value"),
checked: (dom.attr("checked") == "checked" ? true : false)
};
//put object as JSON in array:
toSend.push($.toJSON(domJSON));
}
);
$.ajax({
type:"POST",
url: "salvar_escala.php",
data: {checkbox: toSend},
success: function(response) {
$("#div_salvar").html(response);
},
error: function() {
alert("Erro");
}
}
);
And in PHP I have this:
//Grab the array
$arrayFromAjax = $_POST['checkbox'];
foreach($arrayFromAjax as $aux) {
$temp = json_decode($aux, true);
$id = $temp['id'];
$value = $temp['checked'];
//This line doesn't print anything for $id and $value
echo "Id: $id | Value: $value<br />";
//This line prints an crazy string, but with right values
echo "CHEKBOX[] => $b<br />";
}
In this code, I'm decoding my objects to json, putting then in an array and sending. I also tried but objects in array (without json), and then, convert the array to json, and send them like that:
$.ajax({
type:"POST",
url: "salvar_escala.php",
dataType: "json",
data: {checkbox: $.toJSON(toSend)},
success: function(response) {
$("#div_salvar").html(response);
},
error: function() {
alert("Erro");
}
}
);
But in this case, it's worse, the error function is called.
You should be able to do the following in PHP
<?php
$checkboxes = json_decode($_POST['checkbox']);
foreach($checkboxes as $checkbox) {
$id = $checkbox['id'];
$val = $checkbox['value'];
print $id . ': ' . $val;
}
The problem is that you're trying to loop through a JSON string without first decoding it into a PHP array.

Categories