使用PHP从SQL生成嵌套JSON

时间:2015-04-07 21:43:44

标签: php json mysqli

我正在尝试使用PHP生成一个JSON API,用作我的Android应用程序数据库的远程服务器接口。

我设法生成了这样的JSON:

{
    products: [
        {
            product_name: "Samsung",
            product_category: "phones",
            shop_name: "Gadget Store",
            user_id: "1",
            price: "1999",
            date: "2015-04-05",
            time: "11:14:44"
        },
        {
            product_name: "Samsung",
            product_category: "phones",
            shop_name: "IT Store",
            user_id: "1",
            price: "1899",
            date: "2015-04-01",
            time: "13:00:00"
        },
        {
            product_name: "Motorola",
            product_category: "phones",
            shop_name: "IT Store",
            user_id: "1",
            price: "1499",
            date: "2015-04-02",
            time: "10:31:29"
        }
    ]
}

但我想我需要一个嵌套的JSON,就像这样:

{
    products: [
        {
            product_name: "Samsung",
            product_category: "phones",
            shops: [
                {
                    shop_name: "Gadget Store",
                    user_id: "1",
                    price: "1999",
                    date: "2015-04-05",
                    time: "11:14:44"
                },
                {
                    shop_name: "IT Store",
                    user_id: "1",
                    price: "1899",
                    date: "2015-04-01",
                    time: "13:00:00"
                }
             ],
        },
        {
            product_name: "Motorola",
            product_category: "phones",
            shops: [
                    shop_name: "IT Store",,
                    user_id: "1",
                    price: "199",
                    date: "2015-04-02",,
                    time: "10:31:29"
            ],    
        }
    ]
}

我怎样才能获得这个结果?

sql查询来自3个不同的表。 以下是我目前的代码:

class productDB
{
    public $product_name = "";
    public $product_category = "";
    public $shop_name = "";
    public $user_id = "";
    public $price;
    public $date = "";
    public $time = "";

    function __construct($product_name, $product_category, $shop_name, $user_id, $price, $date, $time)
    {
        $this->product_name = $product_name;
        $this->product_category = $product_category;
        $this->shop_name = $shop_name;
        $this->user_id = $user_id;
        $this->price = $price;
        $this->date = $date;
        $this->time = $time;
    }

class Shop
{
    public $shop_name = "";
    public $user_id = "";
    public $price;
    public $date = "";
    public $time = "";

    function __construct($shop_name, $user_id, $price, $date, $time)
    {
        $this->shop_name = $shop_name;
        $this->user_id = $user_id;
        $this->price = $price;
        $this->date = $date;
        $this->time = $time;
    }
}

class product
{
    public $product_name = "";
    public $product_category = "";
    public $shop = "";

    function __construct($product_name, $product_category, $shop_name, $user_id, $price, $date, $time)
    {
        $this->product_name = $product_name;
        $this->product_category = $product_category;
        $this->shop = new Shop($shop_name, $user_id, $price, $date, $time);
    }
}


$query = "SELECT a.product_name, a.product_category,
                 b.shop_name,
                 c.user_user_id, c.price, c.date, c.time
          FROM price c, item a, shop b
          WHERE c.product_product_id = a.product_id AND c.shop_shop_id = b.shop_id";

$product_array = array();
if ($result = $dbc->query($query)) {

    while ($obj = $result->fetch_object()) {
        $temp_product[] = new ProductDB(

            $obj->product_name,
            $obj->product_category,
            $obj->shop_name,
            $obj->user_id,
            $obj->price,
            $obj->date,
            $obj->time);

        $product_array = $temp_product;
    }

//Give a name to the array
$array_name = 'products';
$product_array = (array($array_name=>$product_array));

$product_object = json_encode($product_array);
echo $product_object;

2 个答案:

答案 0 :(得分:1)

这里有一个不需要子查询的解决方案。

至少在这个示例中,您似乎不需要ProductDB,因此我们将直接使用Product

为了让商店保持在Product对象中,我们需要持有者。我们会将$shop更改为$shops,其中包含Shop个对象的数组。

产品类:

class Product
{
    public $product_name = "";
    public $product_category = "";
    public $shops = null;

    function __construct($product_name, $product_category, $shop_name, $user_id, $price, $date, $time)
    {
        $this->product_name = $product_name;
        $this->product_category = $product_category;
        $this->shops = array(new Shop($shop_name, $user_id, $price, $date, $time));
    }

    public function addShop($shop_name, $user_id, $price, $date, $time)
    {
        // because $shops is a public property we can check if it still is an array
        if (!is_array($this->shops)) {
            $this->shops = array();
        }
        $this->shops[] = new Shop($shop_name, $user_id, $price, $date, $time);
    }
}

嗨,你可以看到有一个新的功能,可以为阵列增加新的商店。

现在是将商店分组到产品中的部分。

$product_array = array();
$currProduct   = null;

if ($result = $dbc->query($query)) {
    while ($obj = $result->fetch_object()) {
        // check if it is a first product or if we have encountered product with different name or category
        if ($currProduct === null
            || $currProduct->product_name !== $obj->product_name
            || $currProduct->product_category !== $obj->product_category) {
            // create new Product with one position in the shops array
            $product = new Product(
                $obj->product_name,
                $obj->product_category,
                $obj->shop_name,
                $obj->user_id,
                $obj->price,
                $obj->date,
                $obj->time);
            $product_array[] = $product;
            // set created product as a currently used
            $currProduct = $product;
        } else {
            // if name and category is the same add shop data to the current product
            $currProduct->addShop(
                $obj->shop_name,
                $obj->user_id,
                $obj->price,
                $obj->date,
                $obj->time);
        }
    }

    $product_array = array('products' => $product_array);
    $product_json = json_encode($product_array);
    echo $product_json;
}

要正确分组数据,有必要对产品数据进行排序。因此,请在查询ORDER BY a.product_name, a.product_category的末尾添加。

那就是它:)让我知道它是如何工作的(如果你将使用它)

此外,如果您要声明类属性private并仍然使用json_encode来获取类的JSON表示,则可以使用JsonSerializable接口。

购物类

class Shop implements \JsonSerializable
{
    private $shop_name = "";
    private $user_id = "";
    private $price;
    private $date = "";
    private $time = "";

    function __construct($shop_name, $user_id, $price, $date, $time)
    {
        $this->shop_name = $shop_name;
        $this->user_id = $user_id;
        $this->price = $price;
        $this->date = $date;
        $this->time = $time;
    }

    public function JsonSerialize()
    {
        return get_object_vars($this);
    }
}

产品类

class Product implements \JsonSerializable
{
    private $product_name = "";
    private $product_category = "";
    private $shops = null;

    function __construct($product_name, $product_category, $shop_name, $user_id, $price, $date, $time)
    {
        $this->product_name = $product_name;
        $this->product_category = $product_category;
        $this->shops = array(new Shop($shop_name, $user_id, $price, $date, $time));
    }

    public function addShop($shop_name, $user_id, $price, $date, $time)
    {
        $this->shops[] = new Shop($shop_name, $user_id, $price, $date, $time);
    }

    function getName()
    {
        return $this->product_name;
    }

    function getCategory()
    {
        return $this->product_category;
    }

    public function JsonSerialize()
    {
        return get_object_vars($this);
    }
}

主要代码

[...]
if ($currProduct === null
    || $currProduct->getName() !== $obj->product_name
    || $currProduct->getCategory() !== $obj->product_category) {
[...]

玩得开心:)

答案 1 :(得分:0)

为了保持一致的JSON结构,第二部分看起来像这样:

{
        product_name: "Motorola",
        product_category: "phones",
        shops: [
            shop_name: "IT Store",
            user_id: "1",
            price: "1499",
            date: "2015-04-02",
            time: "10:31:29"
        ]
}

这样的事情怎么样:

$queryStr_products = "Select * FROM item";
$queryStr_price = "Select b.shop_name, c.user_user_id, c.price, c.date, c.time FROM price c, shop b WHERE b.shop_id = c.product_product_id and c.product_product_id =";

$product_array = array();
if ($result = $dbc->query($queryStr_products)) {
    //Iterate over all products returned
    while ($obj = $result->fetch_object()) {
        $product_array[] = array (
            'product_name' => $obj->product_name,
            'product_category' => $obj->product_category,
            'shops' => getPricesForProducts($obj->product_id)
        );
    }
    $result->close();
}

echo json_encode(array('products'=>$product_array));

/**
 * For clarity purposes
 * This returns an array of all product prices for a particular productID
 */
function getPricesForProducts ($productID) {
    //You may need to get a new DB connection
    if ($result = $dbc2->query($queryStr_price.$productID)) {
        $price_array = array();
        while($obj = $result->fetch_object()) {
            $price_array[] = array (
                'shop_name' => $obj->b.shop_name,
                'user_id' => $obj->c.user_user.id,
                'price' => $obj->c.price,
                'date' => $obj->c.date,
                'time' => $obj->c.time,
            );
        }
        $result->close();
        return $price_array;
    } else {
        //Maybe you want to set shop_name to "No Prices Found" and user_id = 0;
        return array();
    }
}