使用 PHP 从 MySQL 结果输出复杂的 JSON

Posted

技术标签:

【中文标题】使用 PHP 从 MySQL 结果输出复杂的 JSON【英文标题】:Outputting complex JSON from a MySQL result with PHP 【发布时间】:2011-11-28 12:26:46 【问题描述】:

我刚刚完成了 Sencha Touch 教程,效果很好。我目前正在使用 php 将静态 JSON 数据文件(本教程使用)转换为从 mysql 数据库动态生成的数据 (JSON) 文件。本教程中使用的 JSON 文件(示例文件的链接位于下方)具有复杂的结构,我在将我的 SQL 结果转换为教程中使用的确切 JSON 格式时遇到问题。下面列出了源代码的链接。重点放在 JSON 文件上(第三个链接)。如果我可以简单地复制这个文件,那么项目的其余部分就对我有用。

煎茶触控教程位于: http://www.sencha.com/learn/intro-to-the-nested-list-component/

该项目的所有代码都可以位于(我只允许发布两个链接,希望您能解释下面的链接): github dot com / nelstrom / Sencha-Touch-nested-list-demo

静态 JSON 数据文件的示例可以查看:https://github.com/senchalearn/Nested-list-demo/blob/master/data/albums.json

我有一个数据库和 sql,它以以下结构输出数据:

Genre  Artist     Album           Track               Duration 
ROCK   MUSE       Absolution      Intro               0:23
ROCK   MUSE       Absolution      Apolcalypse Please  4:13
ROCK   MUSE       The Resistance  Uprising            5:03
ROCK   SEVENDUST  Next            Hero                3:48
FUNK   PRIMUS     Antipop         The Antipop         5:33
FUNK   PRIMUS     Antipop         Ballad of Bodacious 2:29

我有以下输出 JSON 但格式不正确的 php,不幸的是,它已经尽可能接近了 - 抱歉,我的 PHP 有点平均:)

$result = mysql_query($query,$link) or die('Errant query:  '.$query);
$model = array();

if(mysql_num_rows($result)) 
    while($e = mysql_fetch_assoc($result)) 
        $model['Genre'] = $e['Genre'];
        $model['Artist'] = $e['Artist'];
        $model['Album'] = $e['Album'];
        $model['items'][] = array(
                        'text' => $e['Track'],
                        'duration' => $e['Duration']
        );
    
  

header('Content-type: application/json');
echo json_encode(array('items'=>$model));

以下是上面 PHP 代码输出的 JSON 示例:


    "items": 
        "Genre": "ROCK",
        "Artist": "MUSE",
        "Album": "Absolution",
        "items": [
            
                "text": "Intro",
                "duration": "0:23"
            ,
            
                "text": "Apolcalypse Please",
                "duration": "4:13"
            
        ]
    

很遗憾,这种 JSON 格式不正确。主要问题是循环并在正确的位置应用方括号'['']'。我在下面包含了一个简短的示例:

    
    "items": [
     
       "model": "Genre",
       "items": [
         
           "model": "Artist",
           "items": [
             
               "model": "Album",
               "items": [
                
                  "model": "Track",
                  "duration": 96,
                  "text": "Introduction",
                  "items": [

                  ],
                  "info": "",
                  "leaf": true
                 ,
                 
                  "model": "Track",
                  "duration": 155,
                  "text": "Please Accept My Love",
                  "items": [

                  ],
                  "info": "",
                  "leaf": true
                
              ],
              "text": "Live in Cook County Jail",
              "info": "<p>Live in Cook County Jail is a 1971 live album by B.B. King recorded in Cook County Jail, Chicago, Illinois. It was ranked as number 499 in the book version of Rolling Stone's 500 Greatest Albums of All Time.</p>",
              "leaf": true
            
          ],
          "text": "B.B.King",
          "info": "<p>Riley B. King aka B. B. King (born September 16th, 1925 in Itta Bena, Mississippi) is a well known American blues guitarist and songwriter. He is among the most respected electric guitarists. </p><p>One of King’s trademarks is naming his guitar (Gibson ES335) “Lucilleâ€. In the 1950s in a bar in Twist, Arkansas two men got into a fight, accidentally knocking over a bucket of burning kerosene (used for heating) and setting the establishment on fire. Risking his life, B.B. King ran back into the collapsing building to retrieve his guitar.</p>",
          "leaf": false
        ,
      ],
      "text": "Blues",
      "info": "",
      "leaf": false
    
  ]
 

提前感谢您查看此内容,如果内容冗长,我很抱歉,但我只是想确保我已包含所有内容。如果您需要更多信息,请告诉我。

亲切的问候

【问题讨论】:

只是为了让您理解,您正在使用一个关系数据库并将其一直压缩为一个对象。在实践中,很少这样做(除非它是出于存档目的,我只是自己拍摄数据库的快照......)。相反,使用各种SELECT 查询“过滤”数据子集,以挑选出所需的特定信息。我了解您正在尝试模仿本教程,但您似乎才刚刚开始使用数据库等一般情况,我想在您尝试对每个数据库调用执行类似操作之前,我会告诉您。 【参考方案1】:

我要做的第一件事是尝试重新创建 JSON 格式的数据。快速测试

$array = array(
'items' => array(
    array(
    'model' => 'Genre',
    'items' => array(
        array(
        'model' => 'Artist',
        'items' => array(
            'model' => 'Album',
            'items' => array(array())
        )
        )
    )
    )
)
);
$json = json_encode( $array );
var_dump( $json );

这会提供类似于您需要的 JSON 输出。

然后,您需要将数据库中的数据转换为相关格式的数组。为避免多次通过您正在构建的数组(随着数组变大,这可能需要一段时间),我会将此作为一个两步过程来完成。

第一

$tempData = array();
while($e = mysql_fetch_assoc($result)) 
    $tempData[$e['Genre']][$e['Artist']][$e['Album']][$e['Track']] = $e['Duration']

然后您应该能够遍历 $tempArray 并以正确的格式构建一个数组来创建 JSON。

【讨论】:

【参考方案2】:

您可以使用下面的代码一次性完成此操作。只需确保返回的数据按流派、艺术家、专辑、曲目排序即可。

if(mysql_num_rows($result)) 
   $curr_genre = $curr_artist = $curr_album = $curr_track = '';
   $model = $track = $album = $artist = $genre = array();
   $first_row = 1;
   while ($e = mysql_fetch_assoc($result))
        // every time track changes, create new array and insert into album
        $track['model'] = 'Track';
        $track['info'] = "";
        $track['text'] = $e['Track'];
        $track['duration'] = $e['Duration'];
        $track['leaf'] = TRUE;
        $album['items'][] = $track;
        $track = array();

        // every time album changes, create new array and insert into artist
    if ($curr_album != $e['Album']) 
        $album['model'] = 'Album';
        $album['info'] = "";
        $album['text'] = $curr_album;
        $album['leaf'] = FALSE;
        if (!$first_row) 
    
        // pop the last item as it's taken one from the next album
        $new_item = array_pop(&$album['items']);
        $artist['items'][] = $album;
        $album = array();
        $album['items'][] = $new_item;
        
        $curr_album = $e['Album'];

        

        // every time artist changes, create new array and insert into genre
    if ($curr_artist != $e['Artist']) 
        $artist['model'] = 'Artist';
        $artist['info'] = "";
        $artist['text'] = $curr_artist;
        $artist['leaf'] = FALSE;
        if (!$first_row) 
    
        $genre["items"][] = $artist;
    $artist = array();
    
    $curr_artist = $e['Artist'];
    


        // every time genre changes, create new array and insert into model
    if ($curr_genre != $e['Genre']) 
        $genre['model'] = 'Genre';
        $genre['text'] = $curr_genre;
        $genre['left'] = FALSE;
        if (!$first_row) 
    
        $model["items"][] = $genre;
    $genre = array();
    

    $curr_genre = $e['Genre'];
        

        if ($first_row) 
            $first_row = 0;
        
    
    
    // now just process the last row

        $album['model'] = 'Album';
        $album['info'] = "";
        $album['text'] = $curr_album;
        $album['leaf'] = FALSE;
        $album['items'][] = $track;

        $artist['model'] = 'Artist';
        $artist['info'] = "";
        $artist['text'] = $curr_artist;
        $artist['leaf'] = FALSE;
        $artist['items'][] = $album;

        $genre['model'] = 'Genre';
        $genre['text'] = $curr_genre;
        $genre['left'] = FALSE;
        $genre["items"][] = $artist;

        $model['items'][] = $genre;

【讨论】:

非常感谢,所有回复都非常有帮助!【参考方案3】:

这很棘手。这是一个非常糟糕的数据模型。

您需要添加一些字段,并且可能需要做一些工作,但试试这个。

if(mysql_num_rows($result)) 
    while($e = mysql_fetch_assoc($result)) 
        $genreExisted = 0;
        $albumExisted = 0;
        foreach ($model['items'] as $genreKey => $genre) 
            if ($e['Genre'] == $genre['text']) 
                $genreExisted = 1;
                foreach ($genre['items'] as $albumKey => $album) 
                    if ($e['Album'] == $album['text']) 
                        $albumExisted = 1;
                        //add a new track
                        $model['items'][$genreKey]['items'][$albumKey]['items']["model"] = $e['Track'];
                        $model['items'][$genreKey]['items'][$albumKey]['items']["duration"] = $e['Duration'];
                    
                
                if ($albumExisted != 1) 
                    //add an album inside the genre
                    $model['items'][$genreKey]['items'][]["model"] = "Album";
                    $model['items'][$genreKey]['items'][]["text"] = $e['Album'];
                
                
        
        if ($genreExisted != 1) 
            //add a new genre
            $model['items'][]["model"] = "Genre";
            $model['items'][]["text"] = "Blues";
        
    

【讨论】:

以上是关于使用 PHP 从 MySQL 结果输出复杂的 JSON的主要内容,如果未能解决你的问题,请参考以下文章

从 MySQL 结果创建 PHP 数组

如何php调用oracle存储过程返回的是一个结果集,该怎么从php页面中吧数据循环输出呀

php输出mysqli查询出来的结果

php 如何从mysql输出数组用逗号分隔?

php中mysql的双重输出

新手求助如何在js上使用ajax接收php读取的mysql数据并输出