简体   繁体   中英

why am I getting foreach error when posting with Android Volley to my php?

In my Android app I am using volley to echo my response which should be of the form:

[
    {
        "category":"whatever",
        "name":"whatever",
        "phone":"whatever",
        "comment":"whatever",
        "reviewid":32
    },
    {
        "category":"whatever",
        "name":"whatever",
        "phone":"whatever",
        "comment":"whatever",
        "reviewid":76
    }
]

Instead I am getting as the response:

Warning: Invalid argument supplied for foreach() in php file on line 13

I don't know if I'm posting it wrong from java or if the problem is with my php .

In my app I have:

selectOwnUserReviews = Arrays.toString(category.getUserReviewIds());

When I toast selectOwnUserReviews I can see selectOwnUserReviews is of the format like:

[63,59,42] or [234] or [34,29] etc...

I am trying to post the selectOwnUserReviews array with volley to my php with:

    @Override
    //post info to php
    protected Map<String, String> getParams() {
        Map<String, String> params = new HashMap<String, String>();

        //KEY_REVIEWID_USER is reviewiduser
        params.put(KEY_REVIEWID_USER, selectOwnUserReviews);

        return params;
    }

Here's my php :

<?php

require('file.php');

$ReviewID = $_POST['reviewiduser'];

$results = array();


foreach($ReviewIDs as $ReviewID) {

$sql2 = "SELECT * FROM review WHERE review_id = ?";
$stmt2 = $con->prepare($sql2) or die(mysqli_error($con));
$stmt2->bind_param('i', $ReviewID) or die ("MySQLi-stmt binding failed ".$stmt2->error);
$stmt2->execute() or die ("MySQLi-stmt execute failed ".$stmt2->error);
$result2 = $stmt2->get_result();

        //if user_id has reviews in the db
    while($row = mysqli_fetch_array($result2)) {
        //make an array called $results
                 $results[] = array(
         'category' => $row['cat_name'], 
         'name' => $row['name'],
         'phone' => $row['phone'],
         'comment' => $row['comment'],
         'reviewid' => $row['review_id'],
         );
    }

}
    $json = json_encode($results);

echo $json;


        ?>

Line 13 in my php code is:

foreach($ReviewIDs as $ReviewID) {

Different variable names!

$ReviewID = $_POST['reviewiduser']; //without final s
foreach($ReviewIDs as $ReviewID) {  //with final s.
/*               ^    */

Edit: You say you're still having problems. Probably your $_POST is a string. Try:

$reviewIDs = json_decode($_POST['reviewiduser']);

that will probably make $reviewIDs a proper array to work with foreach.

You're getting the foreach error when posting with Android Volley to your php b/c all input values are strings in PHP and you can not foreach a string.

You perhaps first want to decode the string into an array which you then can foreach over. But if that is inteded by you or not was not clear to me from your question so I can not be very specific about that w/ my answer and only provide this as a general hint. It is often common to decode JSON, but please that must not be the case in your case: http://php.net/json_decode .

Next to that also take care you are using actually the correct variables, as others have pointed out and I'm with them, you need to use the exactly correctly written variable name, even one character off will give you a different variable name which will evaluate to NULL in PHP which you can't foreach over as well like w/ the string.

I was posting from Java to Php as a string and treating it in php like it was an array .

In Java I was posting selectOwnUserReviews which was of the format like "[1,34,78]" . It looked like an array but was all treated as one unit. And even if I tried operations in php I was doing it on [1 and 34 and 78] , not on 1 and 34 and 78 .

So in Java I did:

//convert [56,23,87] to a string
selectOwnUserReviews = Arrays.toString(category.getUserReviewIds());
//remove [ and ] so we have a string of 56,23,87
selectOwnUserReviews = selectOwnUserReviews.substring(1,selectOwnUserReviews.length()-1);

Now I have the string 56,23,87 and I post this string to my php . In my php I use explode to get the individual values, my complete code looking like:

<?php
    require('file.php');

    $ReviewID = $_POST['reviewiduser'];

    $ReviewID = explode(",",$ReviewID);

    $results = array();

    foreach($ReviewID as $ReviewID) {
        $sql2 = "SELECT * FROM review WHERE review_id = ?";
        $stmt2 = $con->prepare($sql2) or die(mysqli_error($con));
        $stmt2->bind_param('i', $ReviewID) or die ("MySQLi-stmt binding failed ".$stmt2->error);
        $stmt2->execute() or die ("MySQLi-stmt execute failed ".$stmt2->error);
        $result2 = $stmt2->get_result();

        while($row = mysqli_fetch_array($result2)) {//make an array called $results
            $results[] = array(
                'category' => $row['cat_name'],
                'name' => $row['name'],
                'phone' => $row['phone'],
                'comment' => $row['comment'],
                'reviewid' => $row['review_id'],
            );
        }
    }

        echo json_encode($results);

?>

Job done.

To expand on the other answers and give a more complete response based on the comments.

As you noted var_dump($_POST) results in the following:

array(1) {
  ["reviewiduser"]=>
  string(4) "[63]"
}

Meaning that your post value is being received as a string of 4 characters, in the format of an array. Rather than the desired array of integers. However you can use json_decode on the value to parse the string into the desired array of integers.

Example: https://3v4l.org/64v30

Since we should never trust the data from the end user, especially cross-platform/site, you should sanitize and validate the data prior to processing it.

Additionally you have a mix of procedural and object oriented uses of mysqli with some missing controls of where mysql can return false or null . It is best to only utilize one style to ensure that your code is cohesive/coherent. As well as cover all cases where a function/method call may return a value other than what is desired, to be better anticipate the desired behavior or failure.

<?php

require __DIR__ . '/file.php';

//ensure the desired post key exists otherwise set a default value
if (!array_key_exists('reviewiduser', $_POST)) {
    $_POST['reviewiduser'] = '[]';
}

//ensure json decode returns as the desired data type
$ReviewIDs = json_decode($_POST['reviewiduser']);
if (!is_array($ReviewIDs)) {
   $ReviewIDs = [];
}

//declare results for use with json_encode
$results = [];

//declare ReviewID as a variable for use with bind_param
$ReviewID = null;

//prepare the database query for multiple executions
$sql2 = 'SELECT cat_name AS category, name, phone, comment, review_id AS reviewid FROM review WHERE review_id = ?';

//create a statement for use with prepare
$stmt2 = $con->stmt_init();
$stmt2->prepare($sql2) or die($con->error);

//bind ReviewID by reference so that it changes for each execute iteration
$stmt2->bind_param('i', $ReviewID) or die ('MySQLi-stmt binding failed ' . $stmt2->error);

//iterate over ReviewIDs
foreach ($ReviewIDs as $ReviewID) {
    //validate the value is of the desired type
    if (!is_numeric($ReviewID)) {
       continue;
    }
    $stmt2->execute() or die ('MySQLi-stmt execute failed ' . $stmt2->error);
    $result2 = $stmt2->get_result() or die('MySQLi-smt get_result failed' . $smt2->error);

    //ensure a result is retrieved from the database
    if ($row = $result2->fetch_assoc()) {
        $results[] = $row;
    }
}
$stmt2->close();

echo json_encode($results);
exit;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM