PHP MYSQL Select OneToMany 作为嵌套 json

PHP MYSQL Select OneToMany as a nested json

我有两个 table,一个是客户 table,另一个是地址 table,它们之间是一对多的。我想 select 所有客户及其各自的地址并显示如下:

{
  id: 222,
  name: John Doe,
  age: 32,
  addresses: [
    { id: 1, address: "some address", customer_id: 222 },
    { id: 2, address: "secondary address", customer_id: 222}
  ]
}

我现在的代码如下:

$sql = "SELECT * FROM customers JOIN addresses ON customers.id = addresses.customer_id";
$result = $connection->query($sql);


$rows = array();

while ($row = $result->fetch_assoc()) {
  $rows[] = $row;
}

print json_encode($rows); 

但它会导致两条数据相同但地址不同的记录属性。我怎样才能实现上面的例子?

示例数据:

客户table:

id  | name | age
222 | John | 32

地址 table:

id | customer_id | address
1  | 222         | Some address
2  | 222         | Secondary address

当前结果:

[
  {
    id: 222,
    name: John,
    age: 32,
    address: Some address
    customer_id: 222
  },
  {
    id: 222,
    name: John,
    age: 32,
    address: Secondary address
    customer_id: 222
  }
]

SQL 脚本:

CREATE TABLE `customers` (
  `id` bigint(20) NOT NULL,
  `name` varchar(50) NOT NULL,
  `age` int(11) NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;


CREATE TABLE `addresses` (
  `id` bigint(20) NOT NULL,
  `address` varchar(150) NOT NULL,
  `customer_id` bigint(20) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;



ALTER TABLE `customers`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `customers`
  MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;

ALTER TABLE `addresses`
  ADD PRIMARY KEY (`id`),
  ADD KEY `customer_id` (`customer_id`);

ALTER TABLE `addresses`
  MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;

ALTER TABLE `addresses`
  ADD CONSTRAINT `addresses_ibfk_1` FOREIGN KEY (`customer_id`) REFERENCES `customers` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
COMMIT;


INSERT INTO `customers` (`id`, `name`, `age`) VALUES
(1, 'John', 32);

INSERT INTO `addresses` (`id`, `address`, `customer_id`) VALUES
(1, 'Some address', 1),
(2, 'Secondary address', 1);

如果您需要在数据库端解决问题,您可以在查询中使用 JSON_ARRAYAGG 函数:

    SELECT 
        `customers`.`id`,
        `customers`.`name`,
        `customers`.`age`,
        JSON_ARRAYAGG(`addresses`.`address`) AS `addresses`
    FROM `customers` 
    JOIN `addresses` ON `customers`.`id` = `addresses`.`customer_id`

Here You can test this query and PHP code

PHP解决方案可以是下一个:

<?php
$sql = "SELECT 
            `customers`.`id`,
            `customers`.`name`,
            `customers`.`age`,
            `addresses`.`address`
        FROM `customers` 
        JOIN `addresses` ON `customers`.`id` = `addresses`.`customer_id`
    ";
$result = $mysqli->query($sql);


$rows = array();

while ($row = $result->fetch_assoc()) {
    if (is_array($rows[$row['id']])) {
        array_push($rows[$row['id']]['address'],$row['address']);
    } else {
        $rows[$row['id']] = $row;
        $rows[$row['id']]['address'] = (array)$rows[$row['id']]['address'];
    }
}

var_export($rows); 

Run MySQL and PHP code online