0

My php generates two JSON arrays like:

[{"category":183,"private_review_ids":[63,59,62]},
{"category":363,"private_review_ids":[331]}, 
{"category":371,"private_review_ids":[341]},
{"category":379,"private_review_ids":[350]}]
[{"category":363,"public_review_ids":[331]},
{"category":373,"public_review_ids":[343]},
{"category":384,"public_review_ids":[356]},
{"category":183,"public_review_ids":[347]}]

How could I merge these arrays so they are just one array of the form below. It is not simply merging the arrays - it is the possible tranferring of the value from one key (public_review_ids) to another key (private_review_ids) within the JSON Object. Here's the form I want the JSON Array:

[{"category":183,"private_review_ids":[63,59,62],"public_review_ids":[347] },
{"category":363,"private_review_ids":[331],"public_review_ids":[]}, 
{"category":371,"private_review_ids":[341],"public_review_ids":[]},
{"category":379,"private_review_ids":[350]},"public_review_ids":[]},
{"category":373,"private_review_ids":[],"public_review_ids":[343]},
{"category":384,"private_review_ids":[],"public_review_ids":[356]}]

As you can see, if the value is in both private_review_ids and public_review_ids, it should appear in just the private_review_ids key.

I tried using array_unique and array_merge but I was having no success, really.

Here's my code:

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

    //here is the user_id, which is the corresponding user_id for username +5555555

$user_id = "21";
//Select all related info in the review_shared table 
//where the contact_id column is equal to $user_id.

//a value in the contact_id column means a review is shared with a person, $user_name,
//who owns that number, $user_id
$sql = "SELECT * FROM review_shared WHERE contact_id = ?";
$stmt2 = $con->prepare($sql) or die(mysqli_error($con));
$stmt2->bind_param('i', $user_id) or die ("MySQLi-stmt binding failed ".$stmt2->error);
$stmt2->execute() or die ("MySQLi-stmt execute failed ".$stmt2->error);
$result2 = $stmt2->get_result();

//fetch all rows associated with the respective contact_id value
//in review_shared table
while ($row = $result2->fetch_assoc()) {

    //get the corresponding cat_id in the row
    $cat_id = $row["cat_id"];

    //get the corresponding review_id in the row
    $review_id = $row["review_id"];
    //make an array called $results
    $results[$row['cat_id']][] = $review_id; 

}

$jsonData = array_map(function($catId) use ($results) {
    return [
        'category' => $catId,
        'private_review_ids' => $results[$catId],
        ];
}, array_keys($results));
echo json_encode($jsonData);


    //**********************

//select all rows where public_or_private column = 2
//in review table
$sql2 = "SELECT * FROM review WHERE public_or_private = 2";
$result2 = mysqli_query($con,$sql2);

    //fetch all associated rows where public_or_private column = 2
    while ($row = $result2->fetch_assoc()) {

    //get the corresponding review_id in the row
    $review2_id = $row["review_id"];

    //get the corresponding cat_id in the row
    $cat2_id = $row["cat_id"];

    //make an array called $results
    $results2[$row['cat_id']][] = $review2_id;              

    }

    $jsonData2 = array_map(function($cat2Id) use ($results2) {
    return [
        'category' => $cat2Id,
        'public_review_ids' => $results2[$cat2Id],
        ];
}, array_keys($results2));
echo json_encode($jsonData2);


?>
1

1 Answer 1

1

If you refactor your code, you can remove the need for iterating over the data 4 times (twice each) by immediately appending the query results into your desired data structure.

If you execute your public and private review queries, such that their results are in variables $publicReviews and $privateReviews then:

<?php

// Public and private review query results
$publicReviews = $stmt1->get_result();
$privateReviews = $stmt2->get_result();

// Prepare combined reviews array
$reviews = [];

// Iterate through private review results and append to combined reviews
while (($row = $privateReviews->fetch_assoc())) {
    $category_id = $row['cat_id'];
    $review_id = $row['review_id'];

    $reviews[$category_id]['category'] = $category_id;
    $reviews[$category_id]['private_review_ids'][] = $review_id;
    $reviews[$category_id]['public_review_ids'] = [];
}

// Iterate through public review results and append to combined reviews
while (($row = $publicReviews->fetch_assoc())) {
    $category_id = $row['cat_id'];
    $review_id = $row['review_id'];

    $reviews[$category_id]['category'] = $category_id;

    // Create empty private reviews array, where it doesn't exist
    if (! isset($reviews[$category_id]['private_review_ids'])) {
        $reviews[$category_id]['private_review_ids'] = [];
    }

    // Add review id to public reviews where it doesn't exist in private reviews
    if (! in_array($review_id, $reviews[$category_id]['private_review_ids'])) {
        $reviews[$category_id]['public_review_ids'][] = $review_id;
    }
}

echo json_encode(array_values($reviews));
Sign up to request clarification or add additional context in comments.

10 Comments

I am getting Parse error: syntax error, unexpected '?' in /var/www/html/CategorySearch.php on line 43 which is the line $reviews[$cat_id]['public_review_ids'] = $reviews[$cat_id]['public_review_ids'] ?? []; When I remove the extra ? I get Parse error: syntax error, unexpected ';' in /var/www/html/CategorySearch.php on line 43
Are you not using PHP7+?
It looks like I have PHP Version 5.5.9-1ubuntu4.21. Should I update? Not that old though, Feb 2017. In any case I am having an issue getting the result in variable $publicReviews, let me look more into it...
PHP 5.5 was EOL in July 2016, so yes, you may want to consider upgrading. As for the variables, $publicReviews, I merely renamed them in my answer for clarity. You just need to get query results in the correct order for the while loops to work. I'll update my answer to make it work without the null coalese operator.
Tx, the JSON should be an array, yes? Right now the output is like: {"383":{"private_review_ids":[353],"public_review_ids":[]},"203":{"private_review_ids":[149],"public_review_ids":[]},"239":{"private_review_ids":[201],"public_review_ids":[]}} I want it to be like: [{"category":"383", "private_review_ids":[353],"public_review_ids":[]},"category":"203","private_review_ids":[149],"public_review_ids":[]},"category":"239","private_review_ids":[201],"public_review_ids":[]}]
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.