php数据库中的json,如何在json对象中创建数组

时间:2019-02-21 06:32:41

标签: php json

我需要显示带有数据库响应的注释,因为我需要异步连接,我需要为json数组传输mysql输出。

因此,我的数据库中有两个表,一个是冷注释,另一个是子注释。 我用于显示的代码

$sql = "SELECT comments.* , subcomment.comment AS subcom FROM comments left join subcomment on comments.id = subcomment.forid ";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
    // output data of each row
        $outp = array();
        $outp = $result->fetch_all(MYSQLI_ASSOC);
} else {
    echo "0 results";
}

但是该代码生成带有多个注释的json,所以如果一个注释有10个响应,我的输出将有10个注释和10个响应,如下所示:

[{
"id":583,
"user_uid":"xxx",
"video_id":"stackoverflow",
"comment":"what did you try?",
"created":"2019-02-19 11:43:15",
"subcom":"nothing special"
},{
"id":583,
"user_uid":"xxx",
"video_id":"stackoverflow",
"comment":"what did you try?",
"created":"2019-02-19 11:43:15",
"subcom":"my sql commands"
},{
"id":583,
"user_uid":"xxx",
"video_id":"stackoverflow",
"comment":"what did you try?",
"created":"2019-02-19 11:43:15",
"subcom":"php? or json"}]

我需要什么? 像这样:

 {
"id":583,
"user_uid":"xxx",
"video_id":"stackoverflow",
"comment":"what did you try?",
"created":"2019-02-19 11:43:15",
"subcom":{
    sub1: "nothing special" , 
    sub2: "my sql commands" , 
    sub3: "php? or json"
}}

或者:

 {
"id":583,
"user_uid":"xxx",
"video_id":"stackoverflow",
"comment":"what did you try?",
"created":"2019-02-19 11:43:15",
"subcom":["nothing special" , "my sql commands" , "php? or json"]
}

如果有人能告诉我这样做的方法,我会很高兴:D

1 个答案:

答案 0 :(得分:1)

您需要将主从关系(“注释”和“子注释”)映射到内存结构上。

您获取主细节记录的方法有点无效,因为您为每个明细行加载了整个主行。我建议将解决方案分成两半,例如首先查询评论,然后仅查询子评论(见下文)。

但是,基本上,根据您提供的查询,您只需要提取一次主数据,然后将详细记录添加到主记录中(如果您已经拥有该主记录)。

要跟踪哪些主记录已添加到结果数组中,我将主记录的主键用作数组键,因为主键可以明确标识该记录。

// Less effective solution - do everything in one query

$sql = "SELECT comments.* , subcomment.comment AS subcom FROM comments left join subcomment on comments.id = subcomment.forid ";
$result = $conn->query($sql);
$outp = array();
foreach ($result->fetch_all(MYSQLI_ASSOC) as $row) {
    // we will use primary key as $outp array index
    $key = $row['id'];  
    if (!isset($outp[$key])) { 
        // this is first time we encountered the master record with that key

        // we need to convert detail row into an array
        $row['subcom'] = array($row['subcom']);

        // save the master record using primary key as index
        $outp[$key] = $row;
    } else {
        // we already encountered master item with key $key,
        // so add another comment to the master record that already exist

        $outp[$key]['subcom'][] = $row['subcom'];
    }
}

// you may want to strip record keys from output array, 
// otherwise you will receive hash instead of JSON array 
// because keys may be non-sequential and json_encode will interpret 
// array as "associative" instead of "numeric"
$outp = array_values($outp);

但是,如果我想提出更有效的解决方案,我会通过以下方式解决它:

// More effective solution - use two queries

$masterQuery = $conn->query("SELECT comments.* FROM comments");
$masterItems = $conn->query($masterQuery)->fetch_all(MYSQLI_ASSOC);
$byKeys = array();
foreach ($masterItems as $row) {
    $row['subcom'] = array(); // create array for detail items
    $byKeys[$row['id']] = $row;    
}

// note: if your keys come from user input, or are not guaranteed 
// to be numbers, you will need to sanitize and/or escape 
// or quote them on this step

// "forid IN (1, 2, 3)"
$where = 'forid IN ('.implode(', ', array_keys($byKeys)).')'; 

$detailQuery = "SELECT comment, forid FROM subcom WHERE {$where}";
$detailItems = $conn->query($detailQuery)->fetch_all(MYSQLI_ASSOC);
foreach ($detailItems as $row) {
    $masterKey = $row['forid'];
    $byKeys[$masterKey]['subcom'][] = $row['comment'];
}

// strip keys from result
$outp = array_values($byKeys);

上面的代码示例只是为了说明原理,因此,如果您只复制并粘贴它们,就不能保证它们能正常工作。