【问题标题】:Fetching constraints in SQL database to JSON in PHP将 SQL 数据库中的约束提取到 PHP 中的 JSON
【发布时间】:2019-08-07 16:30:54
【问题描述】:

假设我有以下汽车制造商和相应汽车的数据库结构:

制造商:

----------------------------------
| manufacturer | founded_in | id |
|--------------|------------|----|
| Daimler AG   | 1927       | 1  |
| Volkswagen AG| 1937       | 2  |
----------------------------------

汽车:

-------------------------------------
| car     | built_in | manufacturer |
|---------|----------|---------------
| C Class | 1993     | 1            |
| E Class | 1993     | 1            |
| Golf    | 1974     | 2            |
-------------------------------------

manufacturersid 列是主键,carsmanufacturer 列有对应的外键约束。

我想使用 PHP json_encode 生成以下 JSON 输出:

{
    "manufacturers": {
        "Daimler AG": {
            "founded in": "1927",
            "cars": [
                "C Class",
                "E Class"
            ]
        },
        "Volkswagen AG": {
            "founded in": "1937",
            "cars": [
                "Golf"
            ]
        }
    }
}

为了让制造商和他们的founded_in 我只是执行:

SELECT manufacturer, founded_in FROM manufacturers

并将它们提取到一个数组中。但是,在进行第二次查询后,如何正确分配汽车?

【问题讨论】:

  • 我猜你可以通过内部连接来做到这一点。
  • 怎么样?我需要一次将多辆汽车分配给一个制造商。

标签: php mysql sql arrays json


【解决方案1】:

您还可以使用对象关系映射器,例如 Respect/Relational

您可以简单地调用:

use Respect\Relational\Mapper;

$mapper  = new Mapper(new PDO($db_string, $db_user, $db_pass));
$results = $mapper->manufacturers->cars->fetchAll();
$json    = json_encode($results);

把繁重的工作交给 API。

【讨论】:

    【解决方案2】:

    如果您使用的是 MySQL 5.7 或更高版本,则可以使用 JSON 聚合函数直接从 SQL 查询生成您期望的输出。我希望这会比在两者之间使用 php 更有效。

    首先,考虑以下聚合查询,JOINs 两个表并为每个制造商创建一个 JSON 对象,并在子数组中包含相关汽车名称的列表:

    SELECT JSON_OBJECT('founded in', m.founded_in, 'cars', JSON_ARRAYAGG(c.car)) js
    FROM manufacturers m
    INNER JOIN cars c ON c.manufacturer = m.id
    GROUP BY m.id, m.founded_in;
    

    这会返回:

    | js                                                   |
    | ---------------------------------------------------- |
    | {"cars": ["C Class", "E Class"], "founded in": 1927} |
    | {"cars": ["Golf"], "founded in": 1937}               |
    

    要产生预期的输出,我们可以将其转换为子查询并添加另一个级别的聚合:

    SELECT JSON_OBJECT('manufacturers', JSON_OBJECTAGG(manufacturer, js)) myjson
    FROM (
        SELECT 
            m.id, 
            m.manufacturer, 
            JSON_OBJECT('founded in', m.founded_in, 'cars', JSON_ARRAYAGG(c.car)) js
        FROM manufacturers m
        INNER JOIN cars c ON c.manufacturer = m.id
        GROUP BY m.id, m.manufacturer, m.founded_in
    ) x
    

    这会产生:

    | myjson                                                                                                                                           |
    | ------------------------------------------------------------------------------------------------------------------------------------------------ |
    | {"manufacturers": {"Daimler AG": {"cars": ["C Class", "E Class"], "founded in": 1927}, "Volkswagen AG": {"cars": ["Golf"], "founded in": 1937}}} |
    

    Demo on DB Fiddle

    【讨论】:

      【解决方案3】:

      可以先查询所有数据

      SELECT m.manufacturer, m.founded_in
        FROM manufacturers AS m
        JOIN cars AS c ON c.manufacturer_id = m.id
      

      然后将其转换为你在 php 中的结构

      $manufacturers = [];
      foreach ($rows as $row) {
          if (!array_key_exists($row['manufacturer'], $manufacturers)) {
              $manufacturers[$row['manufacturer']] = array(
                 'founded_in' => $row['founded_in'],
                 'cars' => array());
          }
      
          array_push($manufactureres[$row['manufacturer']]['cars'], $row['car']);
      }
      
      

      当然,在 php 中有一种更实用的方法可以做到这一点,但你应该可以这样做......

      【讨论】:

      • 那么您是否建议我应该加入两个表,这些表中的制造商列中的所有行都已填充,即使我只有两个?这算是好的做法吗?
      • 嗯,这取决于你有多少数据。您也可以有两个单独的查询,并填充相同的结构。
      • 作为一种习惯,你可以说,让数据库来处理这一切,因为它是为这样的东西而生的。如果成本太高,您可以将虚假值填充到测试数据库中并运行基准测试。
      猜你喜欢
      • 2011-08-28
      • 2017-12-23
      • 2014-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-26
      • 1970-01-01
      相关资源
      最近更新 更多