gpt4 book ai didi

php - 嵌套数组/连接可以用 Php::PDO 完成吗?

转载 作者:行者123 更新时间:2023-12-01 00:00:29 24 4
gpt4 key购买 nike

恐怕我要求太多了,但如果可能的话,我不想编写代码。有一个“用户(ID,USERNAME)”和一个“图片(ID,USER_ID,NAME)”表。如果你想获取用户的图像,你只需使用:

SELECT * FROM users LEFT JOIN pictures ON pictures.USER_ID = users.ID;

但这会返回一个简单的关联数组。我希望看到这样的内容:

 ID => 1
USERNAME => "user1";
pictures => array();

ID => 1
USERNAME => "user2";
pictures => array();

ID => 1
USERNAME => "user3";
pictures => array(
ID => 1
USER_ID => 3
NAME = "picture of user3"
)

所以想看一个嵌套的多维关联数组,不知道是不是对PDO要求太高了。我想我应该在某个地方为 PDO 设置外键。有任何想法吗?可以吗?我是 PDO 新手

最佳答案

简短的回答是否定的,这是不可能的。不过,它与 PDO 无关。它与 MySQL 息息相关:MySQL 不是 PHP。它的工作是存储和获取数据。如果您JOIN 2 个或更多表,并获取结果,那么数据库会很乐意这样做。
然后将“按原样”获取数据,也就是说:以与存储数据几乎相同的方式获取数据。如果你想要一个二维数组,这意味着数据存储在一个表中,该表包含本身就是表的字段。 MySQL 不这样做:它没有嵌套表(例如,MS SQL Server 可以通过将 XML 存储在字段中来做到这一点)。

但是,PHP 可以使用一个简单的循环处理查询返回的数据:

$stmt = $pdo->query(
'SELECT u.*, p.id as picture_id, p.name as picture_name
FROM users u
LEFT JOIN pictures p
ON u.id = p.user_id
');
$endResult = array();
while($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
if (!isset($endResult[$row['id']]))
$endResult[$row['id']] = array(
'id' => $row['id'],
'username' => $row['username'],
'pictures' => array();
);
$endResult[$row['id']]['pictures'][] = array(
'id' => $row['picture_id'],
'name' => $row['picture_name']
);
}

真的就是那么简单。正如您所知:K.I.S.S 是最重要的。下面是纯学术性的。下面列出的代码不应使用,但我有点忘乎所以,不“保留”查询似乎很遗憾我的疯狂时刻产生了……所以我把它贴在这里


此代码不应被使用。曾经!

这样做可能会对您自己、您周围的人以及整个人类造成严重和永久性的伤害。如果您是那种在阅读此答案的其余部分时随时可能会想“嘿,我可能会用这个”的人,请不要继续阅读。并获得帮助。

当然,还有其他选择。例如,您可以通过按用户 ID 对结果集进行分组来减少获取的行数。如果这样做,您将必须 GROUP_CONCATpictures 表中找到的值。我不建议这样做,因为它取代了逻辑:逻辑属于应用程序,而不是数据库服务器或查询,只知道这是可能的:

SELECT u.*,
GROUP_CONCAT(p.id) AS picture_ids,
GROUP_CONCAT(p.name) AS picture_names
FROM users u
LEFT JOIN pictures p?
ON u.id = p.user_id
GROUP BY u.id;

默认情况下,MySQL 将使用逗号作为分隔符连接在pictures 表中找到的值。在这种情况下,只需将结果分解成一个数组即可分解:

$results = array();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
$pictures = array();
$ids = explode(',', $row['picture_ids']);
$names = explode(',', $row['picture_names']);
foreach ($ids as $k => $id)
{
$pictures[] = array(
'id' => $id,
'name' => $names[$k]
);
}
$results[] = array(
'id' => $row['id'],
'username' => $row['username'],
'pictures' => $pictures
);
}

当然,当图片名称包含逗号时,上面的代码将完全失败,因此最好更改 GROUP_CONCAT 使用的分隔符:

GROUP_CONCAT(p.name, '@#@#@')

或者,将 REPLACE 逗号替换为分号:

GROUP_CONCAT(REPLACE(p.name, ',', ';'))

但由于我们深入挖掘:为了一分钱一英镑,您还不如编写一个查询来选择 pictures 数据作为 json 编码字符串。我们需要为此做什么?简单:

  • CONCAT 将数据转换为字符串格式,如 [{"id":%d, "name":"%s"]},其中 %d 将是一个 int,%s 是图片的名称。
  • 我们还必须确保图片的名称不包含 ",因为这会导致 JSON 格式错误。添加转义 \ 是危险的,因为这样反斜杠可能已经存在。
  • 获取数据,json_decode图片数据。

对于这样一个简单的任务,生成的查询非常复杂,但这里是:

SELECT u.*,
CONCAT(
'[',
GROUP_CONCAT(
CONCAT(
'{"id":',
p.id,
',"name":"',
REPLACE(
p.name,
'"',
'"'
),
'"}'
)
),
']'
) AS pictures
FROM users u
LEFT JOIN pictures p
ON u.id = p.user_id
GROUP_BY u.id;

在您的 PHP 脚本中,写入:

$stmt = $pdo->query();//<-- the query from above
$result = array();
while($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
$row['pictures'] = json_decode($row['pictures'], true);
$result[] = $row;
}

但老实说,这不值得这么麻烦。只需按原样执行您的查询,然后编写我在回答开头使用的简单循环。因为这最后一个片段 Though fully functional , 简直是白痴。如果这确实是您希望数据库返回的数据类型,请切换到 NoSQL alternative。像 mongoDB,而不是重新处理这个查询以结束只有疯子才会看到并认为它是可能的东西:

SELECT
CONCAT(
'{"id":',
u.id,
',"username":"',
REPLACE(
u.username,'"','&quot;'
),'","pictures":',
CONCAT(
'[',
GROUP_CONCAT(
CONCAT(
'{"id":',
p.id,
',"name":"',
REPLACE(
p.name,
'"',
'&quot;'
),
'"}'
)
),
']'
),
'}'
) AS full_json
FROM users u
LEFT JOIN pictures p
ON u.id = p.user_id
GROUP_BY u.id;
//in PHP:
$result = array();
while($row = $stmt->fetch(PDO::FETCH_ASSOC))
$result = json_decode($row['full_json'], true);

但如果您想知道:it does work .

关于php - 嵌套数组/连接可以用 Php::PDO 完成吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23990424/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com