我正在尝试制作新闻Feed类型脚本。每个用户都有一系列被视为朋友的用户ID,如果用户ID是当前用户朋友列表的一部分,我试图仅显示来自数据库的信息。它显示了数据库的所有结果,我不确定原因。
如果有人能告诉我更好的方法,或者至少指出我做错了什么,我们将不胜感激!
include('config.php');
$query2 = "SELECT id, userid, action, date FROM newsfeed ORDER BY date DESC"
or die("Query failed");
$result2 = mysqli_query($dbc, $query2);
while ($row = mysqli_fetch_array($result2, MYSQL_NUM)){
$id = $row[0];
$userid = $row[1];
$action = $row[2];
$date = $row[3];
if($userid != $myid){
$areFriends = in_array($userid, $myfriends); //Check if friends
}
if($areFriends = 1){
$query3 = "SELECT username FROM users WHERE `id` = '$userid'"
or die("query failed");
$result3 = mysqli_query($dbc, $query3);
while ($row = $result3->fetch_row()){
$useridname = $row[0];
}
echo(" - ".$id." - ".$useridname." - ".$action."<br />");
$areFriends = 0;
}
}
答案 0 :(得分:1)
我将做出我希望的一些安全假设。
我会让数据库为您完成工作。这样可以最大限度地减少CPU时间,内存和网络带宽(减少对MySQL的调用)。
我会将您的查询更新为
$query = 'SELECT NF.id, NF.userid, U.username NF.action, NF.date '.
'FROM newsfeed AS NF JOIN users AS U ON U.id=NF.userid '.
'WHERE '.
'NF.userid IN ('.implode(',', array_map('intval', $myfriends)).') '.
'ORDER BY date DESC';
这会减少对一个人的通话次数,并且只获取您感兴趣的信息。
警告是,如果$ myfriends数组非常大,您可能会遇到MySQL的最大查询长度(取决于版本和启动选项)。
答案 1 :(得分:1)
您的脚本存在的问题是您在每个循环中将$ areFriend设置为1.
if ($areFriends = 1) // If setting $areFriends to 1 is successful (so true)
if ($areFriends == 1) // If $areFriends equals 1, or true
if ($areFriends === 1) // If $areFriends equals 1 and only 1
执行原始查询的更好方法是使用联接并使用IN
。
像这样...
SELECT u.id as userId, u.username, n.id as newsId, n.action, n.date
FROM newsfeed as n
JOIN users as u on n.userId = u.id
WHERE
userId in (:myFriends) && // User id is in array of myfriend ids
userId != :myId // User is not me
ORDER BY n.date DESC
通过这种方式,您的搜索只会导致在您的朋友ID数组中具有ID的用户执行操作,并且您不需要多次遍历该第二个数组。
修改强>
与@ ErikNedwidek的回答(以及下面的评论)一样,您需要将implode(',', array_map('intval', $myfriends))
添加到IN
部分,因为mysqli不会将数组绑定到参数。
答案 2 :(得分:1)
正如已经提到的,主要问题是,当您说if ($areFriends = 1)
时,您实际将 areFriends
设置为1,然后查看1是否为1是的(它总是如此)。因此,快速解决方法是使用==
代替。
然而,您可以继续前进,并通过完全删除$areFriends
来简化此代码。如果您正在设置变量并在之后立即检查变量,那么其中没有任何意义。相反,只需在$userid
在朋友列表中时执行您想要执行的操作...然后执行此操作而不是设置标记。观看:
# If a user can't friend themselves, then even this `if` is unnecessary.
if($userid != $myid) {
if (in_array($userid, $myfriends)) {
$friend_query = "SELECT username FROM users WHERE `id` = '$userid'";
# fixed this for you, btw. you want the `or ...` after the mysqli_query,
# since that's what can fail. :P
$friend_result = mysqli_query($dbc, $friend_query)
or die("query failed");
# If you'll only have one row, use `if`.
if (($friend = $friend_result->fetch_assoc())) {
echo(" - $id - {$friend['username']} - $action<br />");
}
}
}
使用$areFriends
也会出现奇怪的情况&#34;如果它是真的,那就去做吧,然后把它做成假的&#34;东西。
你可以更多地改进一些事情,但是...但是如何取决于你的朋友阵列的来源。
例如,如果它位于正确规范化的表格中,您只需在表格上进行连接即可。
我们假设您有user_friends
表格,例如user_id
和friend_id
。每一行
在表格中基本上表示用户user_id
已经与用户friend_id
建立了联系。
使用这样的表格,您甚至不必通过好友列表。你可以做一个INNER JOIN
在user_id
列与$myid
匹配的表格上。
$myid = intval($myid); # no need to demonstrate sql injection :P
$news_query = "
SELECT news.id, u.username useridname, news.action, news.date
FROM newsfeed news
INNER JOIN user_friends friends ON friends.friend_id = news.userid
INNER JOIN users u ON u.userid = friends.friend_id
WHERE friends.user_id = $myid
ORDER BY news.date DESC
";
如果它只是你在路边找到的一个数组,那么你需要构建SQL来传递一个列表。
$friend_ids = implode(', ', array_map('intval', $myfriends));
$news_query = "
SELECT news.id, u.username useridname, news.action, news.date
FROM newsfeed news
INNER JOIN users u ON u.userid = news.userid
WHERE news.userid IN ($friend_ids)
ORDER BY news.date DESC
";
无论哪种方式,而不是第二次去查找用户名或跳过非朋友,你都需要获取所需的列 - 而只你需要的行 - - 一下子。
一旦你拥有了这个SQL,它就会琐事来运行查询结果和列表内容。例如,与朋友表...
$myid = intval($myid); # no need to demonstrate sql injection :P
$news_query = "
SELECT news.id, u.username useridname, news.action, news.date
FROM newsfeed news
INNER JOIN user_friends friends ON friends.friend_id = news.userid
INNER JOIN users u ON u.userid = friends.friend_id
WHERE friends.user_id = $myid
ORDER BY news.date DESC
";
$news_result = $dbc->query($news_query) or die("Query failed");
while (($news = $news_result->fetch_assoc())) {
echo " - {$news['id']} - {$news['useridname']} - {$news['action']}<br />";
}
Aaaaa和完成。此代码显示的内容与您拥有的内容大致相同。 (主要的潜在输出差异是$myid
在他们自己的朋友列表中时发生的情况。但是这可以合并到SQL中。)
基本上它不做的最大的事情是设置一堆变量,重新检查好友列表,或者重新查询数据库中的用户名。您不再需要这样做,因为查询已经告诉MySQL您想要的行和列。
答案 3 :(得分:0)
你需要以不同的方式进行比较;您只检查$areFriends
是否存在。因此,如果$userid
不等于$myid
,它将始终返回true。
看看这个比较方法的简单例子:
$myid = "1"; // hypothetical examples
$userid = "10";
$myfriends = array( 'friends' => array( 10, 3, 11, 33, 42));
if ($userid != $myid) {
if (in_array($userid, $myfriends['friends'])) { // Check if friends
$areFriends = "TRUE";
} else {
$areFriends = "FALSE";
}
}
if ($areFriends == "TRUE") {
echo "you are friends with id ".$userid;
} else {
echo "you are not friends with id ".$userid;
}
它应该阐明如何选择正确的值并进行比较。