来自 MySQL 查询的多个嵌套数组 PHP
Multiple nested array from MySQL query in PHP
我正在使用 foreach 循环访问嵌套数组中的记录。
我需要嵌套3个数组(所以第一个数组包含一个数组,它也包含一个数组)。我在 2 个阵列上取得了成功,但我无法让 3 个阵列正常工作。
我的代码使用了 2 个数组(效果很好),但我无法嵌套 3 个数组。
这是我想要的结果:
[
{
"site_id": "1",
"user_plants": [
{
"user_plant_id": "1",
"site_id": "1",
"plant_id": "1",
"plant_images": [
{
"plant_image_id": "1"
},
{
"plant_image_id": "2"
},
{
"plant_image_id": "3"
},
]
}
]
}
]
我当前的代码:
$query = "SELECT A.site_id FROM sites A WHERE A.user_id='".$user_id."' GROUP BY A.site_id";
$result = $this->conn->query($query);
$json_response = array();
$sites = array();
if ($result-> num_rows > 0) {
while ($item = $result->fetch_object())
$sites[] = $item;
foreach($sites as $item) {
$row_array = (array)$item;
$site_id = $item->site_id;
$user_plants = "SELECT A.user_plant_id, A.site_id, A.plant_id FROM user_plants A RIGHT JOIN sites B ON A.site_id ='".$site_id."'
JOIN plants C ON A.plant_id = C.plant_id GROUP BY A.user_plant_id";
$resultSet = $this->conn->query($user_plants);
$user_plants = array();
if ($resultSet-> num_rows > 0) {
while ($item = $resultSet->fetch_object())
$user_plants[] = $item;
foreach ($user_plants as $item) {
$row_array['user_plants'][] = (array)$item;
$plant_id = $item->plant_id;
$user_plant_id = $item->user_plant_id;
$plant_images = "SELECT A.plant_image_id FROM plants_images A WHERE A.plant_id ='".$plant_id."' UNION SELECT B.plant_image_id FROM user_plant_image B JOIN user_plants C ON B.user_plant_id ='".$user_plant_id."' WHERE C.user_id ='".$user_id."' GROUP BY B.plant_image_id ORDER BY plant_image_id";
$resultSet = $this->conn->query($plant_images);
$plant_images = array();
if ($resultSet->num_rows > 0) {
while ($item = $resultSet->fetch_object())
$plant_images[] = $item;
foreach ($plant_images as $item) {
$row_array['user_plants'][]['plant_images'][] = $item;
}
} else if ($resultSet->num_rows == 0) {
$row_array['plant_images'] = [];
}
}
$json_response[] = $row_array;
}
}
}
return $json_response;
以上代码的结果:
[
{
"site_id": "1",
"user_plants": [
{
"user_plant_id": "1",
"site_id": "1",
"plant_id": "1"
},
{
"plant_images": [
{
"plant_image_id": "1"
},
{
"plant_image_id": "2"
},
{
"plant_image_id": "3"
},
]
}
]
}
]
我应该如何调整上面的 foreach 循环以适应这种情况?
这段代码还有很多改进的余地,但我忽略了这一点,并尽量使代码与本示例中的代码保持一致。
主要变化是:
- 创建一个临时变量
$user_plant_array
,我们将“plant_images”存储在
- 在循环结束时将该临时变量推送到
$site_array
- 重命名一些循环变量,以便更容易识别您引用的内容
$json_response = array();
$sites = array();
if ($result->num_rows > 0) {
while ($site = $result->fetch_object()) {
$sites[] = $site;
}
foreach ($sites as $site) {
$site_array = (array)$site;
$site_id = $site->site_id;
$user_plants = "SELECT A.user_plant_id, A.site_id, A.plant_id FROM user_plants A RIGHT JOIN sites B ON A.site_id ='" . $site_id . "'
JOIN plants C ON A.plant_id = C.plant_id GROUP BY A.user_plant_id";
$resultSet = $this->conn->query($user_plants);
$user_plants = array();
if ($resultSet->num_rows > 0) {
while ($user_plant = $resultSet->fetch_object())
$user_plants[] = $user_plant;
foreach ($user_plants as $user_plant) {
// create a temporary variable here that we will map
// all "plant_images" to
$user_plant_array = (array)$user_plant;
$plant_id = $user_plant->plant_id;
$user_plant_id = $user_plant->user_plant_id;
$plant_images = "SELECT A.plant_image_id FROM plants_images A WHERE A.plant_id ='" . $plant_id . "' UNION SELECT B.plant_image_id FROM user_plant_image B JOIN user_plants C ON B.user_plant_id ='" . $user_plant_id . "' WHERE C.user_id ='" . $user_id . "' GROUP BY B.plant_image_id ORDER BY plant_image_id";
$resultSet = $this->conn->query($plant_images);
$plant_images = array();
if ($resultSet->num_rows > 0) {
while ($plant_image = $resultSet->fetch_object())
$plant_images[] = $plant_image;
foreach ($plant_images as $plant_image) {
$user_plant_array['plant_images'][] = $plant_image;
}
} else if ($resultSet->num_rows == 0) {
$user_plant_array['plant_images'] = [];
}
// the temporary variable now contains all "plant_images"
// now we can push that to the site array
$site_array['user_plants'][] = $user_plant_array;
}
$json_response[] = $site_array;
}
}
}
return $json_response;
通过一些代码改进创建一个单独的答案作为替代解决方案。
“改进”可读性更高 and/or 性能更高。
我建议作为“改进”的一些主要更改已在此示例中实现。主要是:
- 使用准备好的 SQL 语句(并不总是必需的,但使用起来是个好习惯,尤其是在任何接受用户输入的地方,也可以使代码更清晰)
- 减少循环次数(在一些地方你循环只是为了创建一个数组然后再次循环)
- Returning/continuing 尽可能早(有助于防止不必要的嵌套)
- 删除不必要的 if 语句(例如,如果结果为空,将跳过大部分 while 循环 - 事先检查并非完全必要)
- 更具可读性的变量名称(新编码人员通常会尝试缩写很多变量并且经常使用过头 - 使它们可读会在调试时为您节省大量时间)
使用 mysqli
的代码可能不是最好的,因为我通常使用 PDO
。
function getSitesData() {
// assumes that $user_id is set somewhere before this
// assumes that $this->conn references a valid database connection
$sql = "SELECT A.site_id FROM sites A WHERE A.user_id = ? GROUP BY A.site_id";
$query = $this->conn->prepare($sql);
$query->bind_param("i", $user_id);
$query->execute();
$site_result = $query->get_result();
$sites = [];
while ($site = $site_result->fetch_assoc()) {
// using fetch_assoc gives us an associative array
// initialise empty array
$site["user_plants"] = [];
// get user_plants
$sql = "SELECT A.user_plant_id, A.site_id, A.plant_id FROM user_plants A RIGHT JOIN sites B ON A.site_id = ?
JOIN plants C ON A.plant_id = C.plant_id GROUP BY A.user_plant_id";
$query = $this->conn->prepare($sql);
$query->bind_param("i", $site["site_id"]);
$query->execute();
$user_plant_result = $query->get_result();
while ($user_plant = $user_plant_result->fetch_assoc()) {
// intialise empty array
$user_plant["plant_images"] = [];
// get plant images
$sql = "SELECT A.plant_image_id FROM plants_images A WHERE A.plant_id = ? UNION SELECT B.plant_image_id FROM user_plant_image B JOIN user_plants C ON B.user_plant_id = ? WHERE C.user_id = ? GROUP BY B.plant_image_id ORDER BY plant_image_id";
$query = $this->conn->prepare($sql);
$query->bind_param("iii", $user_plant["plant_id"], $user_plant["user_plant_id"], $user_id);
$query->execute();
$plant_image_result = $query->get_result();
while ($plant_image = $plant_image_result->fetch_assoc()) {
$user_plant["plant_images"][] = $plant_image;
}
$sites["user_plants"][] = $user_plant;
}
$sites[] = $site;
}
return $sites;
}
我正在使用 foreach 循环访问嵌套数组中的记录。
我需要嵌套3个数组(所以第一个数组包含一个数组,它也包含一个数组)。我在 2 个阵列上取得了成功,但我无法让 3 个阵列正常工作。
我的代码使用了 2 个数组(效果很好),但我无法嵌套 3 个数组。
这是我想要的结果:
[
{
"site_id": "1",
"user_plants": [
{
"user_plant_id": "1",
"site_id": "1",
"plant_id": "1",
"plant_images": [
{
"plant_image_id": "1"
},
{
"plant_image_id": "2"
},
{
"plant_image_id": "3"
},
]
}
]
}
]
我当前的代码:
$query = "SELECT A.site_id FROM sites A WHERE A.user_id='".$user_id."' GROUP BY A.site_id";
$result = $this->conn->query($query);
$json_response = array();
$sites = array();
if ($result-> num_rows > 0) {
while ($item = $result->fetch_object())
$sites[] = $item;
foreach($sites as $item) {
$row_array = (array)$item;
$site_id = $item->site_id;
$user_plants = "SELECT A.user_plant_id, A.site_id, A.plant_id FROM user_plants A RIGHT JOIN sites B ON A.site_id ='".$site_id."'
JOIN plants C ON A.plant_id = C.plant_id GROUP BY A.user_plant_id";
$resultSet = $this->conn->query($user_plants);
$user_plants = array();
if ($resultSet-> num_rows > 0) {
while ($item = $resultSet->fetch_object())
$user_plants[] = $item;
foreach ($user_plants as $item) {
$row_array['user_plants'][] = (array)$item;
$plant_id = $item->plant_id;
$user_plant_id = $item->user_plant_id;
$plant_images = "SELECT A.plant_image_id FROM plants_images A WHERE A.plant_id ='".$plant_id."' UNION SELECT B.plant_image_id FROM user_plant_image B JOIN user_plants C ON B.user_plant_id ='".$user_plant_id."' WHERE C.user_id ='".$user_id."' GROUP BY B.plant_image_id ORDER BY plant_image_id";
$resultSet = $this->conn->query($plant_images);
$plant_images = array();
if ($resultSet->num_rows > 0) {
while ($item = $resultSet->fetch_object())
$plant_images[] = $item;
foreach ($plant_images as $item) {
$row_array['user_plants'][]['plant_images'][] = $item;
}
} else if ($resultSet->num_rows == 0) {
$row_array['plant_images'] = [];
}
}
$json_response[] = $row_array;
}
}
}
return $json_response;
以上代码的结果:
[
{
"site_id": "1",
"user_plants": [
{
"user_plant_id": "1",
"site_id": "1",
"plant_id": "1"
},
{
"plant_images": [
{
"plant_image_id": "1"
},
{
"plant_image_id": "2"
},
{
"plant_image_id": "3"
},
]
}
]
}
]
我应该如何调整上面的 foreach 循环以适应这种情况?
这段代码还有很多改进的余地,但我忽略了这一点,并尽量使代码与本示例中的代码保持一致。
主要变化是:
- 创建一个临时变量
$user_plant_array
,我们将“plant_images”存储在 - 在循环结束时将该临时变量推送到
$site_array
- 重命名一些循环变量,以便更容易识别您引用的内容
$json_response = array();
$sites = array();
if ($result->num_rows > 0) {
while ($site = $result->fetch_object()) {
$sites[] = $site;
}
foreach ($sites as $site) {
$site_array = (array)$site;
$site_id = $site->site_id;
$user_plants = "SELECT A.user_plant_id, A.site_id, A.plant_id FROM user_plants A RIGHT JOIN sites B ON A.site_id ='" . $site_id . "'
JOIN plants C ON A.plant_id = C.plant_id GROUP BY A.user_plant_id";
$resultSet = $this->conn->query($user_plants);
$user_plants = array();
if ($resultSet->num_rows > 0) {
while ($user_plant = $resultSet->fetch_object())
$user_plants[] = $user_plant;
foreach ($user_plants as $user_plant) {
// create a temporary variable here that we will map
// all "plant_images" to
$user_plant_array = (array)$user_plant;
$plant_id = $user_plant->plant_id;
$user_plant_id = $user_plant->user_plant_id;
$plant_images = "SELECT A.plant_image_id FROM plants_images A WHERE A.plant_id ='" . $plant_id . "' UNION SELECT B.plant_image_id FROM user_plant_image B JOIN user_plants C ON B.user_plant_id ='" . $user_plant_id . "' WHERE C.user_id ='" . $user_id . "' GROUP BY B.plant_image_id ORDER BY plant_image_id";
$resultSet = $this->conn->query($plant_images);
$plant_images = array();
if ($resultSet->num_rows > 0) {
while ($plant_image = $resultSet->fetch_object())
$plant_images[] = $plant_image;
foreach ($plant_images as $plant_image) {
$user_plant_array['plant_images'][] = $plant_image;
}
} else if ($resultSet->num_rows == 0) {
$user_plant_array['plant_images'] = [];
}
// the temporary variable now contains all "plant_images"
// now we can push that to the site array
$site_array['user_plants'][] = $user_plant_array;
}
$json_response[] = $site_array;
}
}
}
return $json_response;
通过一些代码改进创建一个单独的答案作为替代解决方案。
“改进”可读性更高 and/or 性能更高。
我建议作为“改进”的一些主要更改已在此示例中实现。主要是:
- 使用准备好的 SQL 语句(并不总是必需的,但使用起来是个好习惯,尤其是在任何接受用户输入的地方,也可以使代码更清晰)
- 减少循环次数(在一些地方你循环只是为了创建一个数组然后再次循环)
- Returning/continuing 尽可能早(有助于防止不必要的嵌套)
- 删除不必要的 if 语句(例如,如果结果为空,将跳过大部分 while 循环 - 事先检查并非完全必要)
- 更具可读性的变量名称(新编码人员通常会尝试缩写很多变量并且经常使用过头 - 使它们可读会在调试时为您节省大量时间)
使用 mysqli
的代码可能不是最好的,因为我通常使用 PDO
。
function getSitesData() {
// assumes that $user_id is set somewhere before this
// assumes that $this->conn references a valid database connection
$sql = "SELECT A.site_id FROM sites A WHERE A.user_id = ? GROUP BY A.site_id";
$query = $this->conn->prepare($sql);
$query->bind_param("i", $user_id);
$query->execute();
$site_result = $query->get_result();
$sites = [];
while ($site = $site_result->fetch_assoc()) {
// using fetch_assoc gives us an associative array
// initialise empty array
$site["user_plants"] = [];
// get user_plants
$sql = "SELECT A.user_plant_id, A.site_id, A.plant_id FROM user_plants A RIGHT JOIN sites B ON A.site_id = ?
JOIN plants C ON A.plant_id = C.plant_id GROUP BY A.user_plant_id";
$query = $this->conn->prepare($sql);
$query->bind_param("i", $site["site_id"]);
$query->execute();
$user_plant_result = $query->get_result();
while ($user_plant = $user_plant_result->fetch_assoc()) {
// intialise empty array
$user_plant["plant_images"] = [];
// get plant images
$sql = "SELECT A.plant_image_id FROM plants_images A WHERE A.plant_id = ? UNION SELECT B.plant_image_id FROM user_plant_image B JOIN user_plants C ON B.user_plant_id = ? WHERE C.user_id = ? GROUP BY B.plant_image_id ORDER BY plant_image_id";
$query = $this->conn->prepare($sql);
$query->bind_param("iii", $user_plant["plant_id"], $user_plant["user_plant_id"], $user_id);
$query->execute();
$plant_image_result = $query->get_result();
while ($plant_image = $plant_image_result->fetch_assoc()) {
$user_plant["plant_images"][] = $plant_image;
}
$sites["user_plants"][] = $user_plant;
}
$sites[] = $site;
}
return $sites;
}