在获取的数据中添加额外的变量
adding extra variable inside fetched data
正如您在下面看到的,我正在获取 idsOfSenders
并且我正在执行另一个查询以获取该用户的信息。到目前为止一切正常。
但是如您所见,我还有另一个变量 $msgDate
,我想将其放入每个用户的输出中。我该怎么做?
$recieverId = 33;
$query = "SELECT from_msg, chat_date FROM msg WHERE `to_msg` = '$recieverId' ORDER BY `chat_date` DESC";
$res = mysqli_query($conn, $query);
while($row = mysqli_fetch_array($res)) {
$idsOfSenders[] = $row['from_msg'];
$msgDate[] = $row['chat_date'];
}
$queryb = "SELECT fullname, username FROM `users` WHERE `id` IN('".implode("','",$idsOfSenders)."')";
$resb = mysqli_query($conn, $queryb);
if($resb->num_rows >0){
$json=[];
while(($rowb = $resb->fetch_assoc())) {
$json[] = $rowb;
}
echo json_encode($json);
} else {
echo "0";
}
case 'gmmn':
//ini_set('display_errors', 1);
//ini_set('display_startup_errors', 1);
//error_reporting(E_ALL);
if(isTheseParametersAvailable(array('i'))){
if (!$conn) {
return;
}
//$recieverId = str_replace(" ", "", $_POST["i"]);
$recieverId = 33;
$sqlCheckMsg = "SELECT from_msg, chat_date, fullname, username FROM msgNew LEFT JOIN users_table on users_table.id = msgNew.from_msg WHERE to_msg = ? ORDER BY `chat_date` DESC";
$stmt = $conn->prepare($sqlCheckMsg );
$stmt->bind_param("i",$recieverId);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($from_msg,$chat_date,$fullname,$username);
if($stmt->num_rows > 0){
$rows=[];
while($stmt->fetch()) {
$rows[] = array('from_msg'=>$from_msg
, 'chat_date'=>$chat_date
, 'fullname'=>$fullname
, 'username'=>$username);
}
} else {
echo "0";
return;
}
echo json_encode($rows);
}
break;
这就是 JOIN
派上用场的地方。您对两个查询所做的事情可以在一个查询中完成,而且作为一个加号,不需要那种可怕的 implode
注入:
SELECT from_msg, chat_date, fullname, username
FROM msg
LEFT JOIN users on users.id=msg.from_msg
WHERE to_msg=? ORDER BY `chat_date` DESC
这应该 显着 更快更安全,因为它在返回数据库之前不涉及 round-trip 到 PHP。
Note: Ensure that msg
is indexed on from_msg
to make this JOIN
operation efficient. You can check the query performance with EXPLAIN SELECT ...
毫无疑问,您应该使用@tadman 的回答。话虽如此,您遇到的主要问题是单个用户可以向接收者发送任意数量的消息。
假设我是 usera
并且我在一周前、昨天和今天向 receiverId 33
发送了消息。有 3 条消息有 3 个不同的日期。您需要为该用户设置 3 行,以反映 3 条消息。
我不建议您使用以下方法,但它会起作用,具体取决于您如何看待它,解决用户可以发送多个具有关联 chat_date.此代码将消息存储在一个数组中,并将它们添加到每个用户的获取结果中。您仍然需要处理这样一个事实,即 'chat_date' 是一个日期数组,而不是像结果集的其余部分那样的单个标量值。
$recieverId = 33;
$query = "SELECT from_msg, chat_date FROM msg WHERE `to_msg` = '$recieverId' ORDER BY `chat_date` DESC";
$res = mysqli_query($conn, $query);
while($row = mysqli_fetch_array($res)) {
$idsOfSenders[] = $row['from_msg'];
//msgDate will be an array of all the dates sent for this member to the other member
$msgDate[$row['from_msg']][] = $row['chat_date'];
}
$queryb = "SELECT id, fullname, username FROM `users` WHERE `id` IN('".implode("','",$idsOfSenders)."')";
$resb = mysqli_query($conn, $queryb);
if($resb->num_rows >0){
$json=[];
while(($rowb = $resb->fetch_assoc())) {
// Add the array of this user's sent message dates
$rowb['msg_date'] = $msgDate[$rowb['id']];
// get rid of the users.id column if you don't want it
unset($rowb['id']);
$json[] = $rowb;
}
echo json_encode($json);
} else {
echo "0";
}
这假设用户的 table 主键名为 id。如果不是,则需要更改相关代码以反映存储在消息 table.[=] 的 from_msg 和 to_msg 中的用户 table 主键的名称。 14=]
如您所见,这是一个丑陋的 hack。关系数据库会为您处理这件事。同样,@tadman 的解决方案是可行的方法,但我认为它可能会帮助您更好地理解当前的问题,如果我向您展示了如何使其工作以及您遗漏的东西。
更新:既然你实现了@tadman 的查询,我个人不会绑定结果,因为这会导致你在这种情况下使用很多你并不真正关心的变量。这个更简单:
$sqlCheckMsg = "SELECT from_msg, chat_date, fullname, username FROM msgNew LEFT JOIN users_table on users_table.id = msgNew.from_msg WHERE to_msg = ? ORDER BY `chat_date` DESC";
$stmt = $conn->prepare($sqlCheckMsg );
$stmt->bind_param("i",$recieverId);
$stmt->execute();
$result = $stmt->get_result();
$rows = array();
while ($row = $result->fetch_assoc()) {
$rows[] = $row;
}
if (count($rows) > 0) {
echo json_encode($rows);
return;
} else {
echo "0";
return;
}
正如您在下面看到的,我正在获取 idsOfSenders
并且我正在执行另一个查询以获取该用户的信息。到目前为止一切正常。
但是如您所见,我还有另一个变量 $msgDate
,我想将其放入每个用户的输出中。我该怎么做?
$recieverId = 33;
$query = "SELECT from_msg, chat_date FROM msg WHERE `to_msg` = '$recieverId' ORDER BY `chat_date` DESC";
$res = mysqli_query($conn, $query);
while($row = mysqli_fetch_array($res)) {
$idsOfSenders[] = $row['from_msg'];
$msgDate[] = $row['chat_date'];
}
$queryb = "SELECT fullname, username FROM `users` WHERE `id` IN('".implode("','",$idsOfSenders)."')";
$resb = mysqli_query($conn, $queryb);
if($resb->num_rows >0){
$json=[];
while(($rowb = $resb->fetch_assoc())) {
$json[] = $rowb;
}
echo json_encode($json);
} else {
echo "0";
}
case 'gmmn':
//ini_set('display_errors', 1);
//ini_set('display_startup_errors', 1);
//error_reporting(E_ALL);
if(isTheseParametersAvailable(array('i'))){
if (!$conn) {
return;
}
//$recieverId = str_replace(" ", "", $_POST["i"]);
$recieverId = 33;
$sqlCheckMsg = "SELECT from_msg, chat_date, fullname, username FROM msgNew LEFT JOIN users_table on users_table.id = msgNew.from_msg WHERE to_msg = ? ORDER BY `chat_date` DESC";
$stmt = $conn->prepare($sqlCheckMsg );
$stmt->bind_param("i",$recieverId);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($from_msg,$chat_date,$fullname,$username);
if($stmt->num_rows > 0){
$rows=[];
while($stmt->fetch()) {
$rows[] = array('from_msg'=>$from_msg
, 'chat_date'=>$chat_date
, 'fullname'=>$fullname
, 'username'=>$username);
}
} else {
echo "0";
return;
}
echo json_encode($rows);
}
break;
这就是 JOIN
派上用场的地方。您对两个查询所做的事情可以在一个查询中完成,而且作为一个加号,不需要那种可怕的 implode
注入:
SELECT from_msg, chat_date, fullname, username
FROM msg
LEFT JOIN users on users.id=msg.from_msg
WHERE to_msg=? ORDER BY `chat_date` DESC
这应该 显着 更快更安全,因为它在返回数据库之前不涉及 round-trip 到 PHP。
Note: Ensure that
msg
is indexed onfrom_msg
to make thisJOIN
operation efficient. You can check the query performance withEXPLAIN SELECT ...
毫无疑问,您应该使用@tadman 的回答。话虽如此,您遇到的主要问题是单个用户可以向接收者发送任意数量的消息。
假设我是 usera
并且我在一周前、昨天和今天向 receiverId 33
发送了消息。有 3 条消息有 3 个不同的日期。您需要为该用户设置 3 行,以反映 3 条消息。
我不建议您使用以下方法,但它会起作用,具体取决于您如何看待它,解决用户可以发送多个具有关联 chat_date.此代码将消息存储在一个数组中,并将它们添加到每个用户的获取结果中。您仍然需要处理这样一个事实,即 'chat_date' 是一个日期数组,而不是像结果集的其余部分那样的单个标量值。
$recieverId = 33;
$query = "SELECT from_msg, chat_date FROM msg WHERE `to_msg` = '$recieverId' ORDER BY `chat_date` DESC";
$res = mysqli_query($conn, $query);
while($row = mysqli_fetch_array($res)) {
$idsOfSenders[] = $row['from_msg'];
//msgDate will be an array of all the dates sent for this member to the other member
$msgDate[$row['from_msg']][] = $row['chat_date'];
}
$queryb = "SELECT id, fullname, username FROM `users` WHERE `id` IN('".implode("','",$idsOfSenders)."')";
$resb = mysqli_query($conn, $queryb);
if($resb->num_rows >0){
$json=[];
while(($rowb = $resb->fetch_assoc())) {
// Add the array of this user's sent message dates
$rowb['msg_date'] = $msgDate[$rowb['id']];
// get rid of the users.id column if you don't want it
unset($rowb['id']);
$json[] = $rowb;
}
echo json_encode($json);
} else {
echo "0";
}
这假设用户的 table 主键名为 id。如果不是,则需要更改相关代码以反映存储在消息 table.[=] 的 from_msg 和 to_msg 中的用户 table 主键的名称。 14=]
如您所见,这是一个丑陋的 hack。关系数据库会为您处理这件事。同样,@tadman 的解决方案是可行的方法,但我认为它可能会帮助您更好地理解当前的问题,如果我向您展示了如何使其工作以及您遗漏的东西。
更新:既然你实现了@tadman 的查询,我个人不会绑定结果,因为这会导致你在这种情况下使用很多你并不真正关心的变量。这个更简单:
$sqlCheckMsg = "SELECT from_msg, chat_date, fullname, username FROM msgNew LEFT JOIN users_table on users_table.id = msgNew.from_msg WHERE to_msg = ? ORDER BY `chat_date` DESC";
$stmt = $conn->prepare($sqlCheckMsg );
$stmt->bind_param("i",$recieverId);
$stmt->execute();
$result = $stmt->get_result();
$rows = array();
while ($row = $result->fetch_assoc()) {
$rows[] = $row;
}
if (count($rows) > 0) {
echo json_encode($rows);
return;
} else {
echo "0";
return;
}