检查数组PHP的朋友

时间:2014-06-14 23:24:26

标签: php mysql

我正在尝试制作新闻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;
}
} 

4 个答案:

答案 0 :(得分:1)

我将做出我希望的一些安全假设。

  • 您只需要来自朋友的内容并忽略非朋友。
  • 您的newsfeed.userid是users.id的外键,它是一个INT值(或者更确切地说,即使它没有作为正式约束添加它也是如此)。

我会让数据库为您完成工作。这样可以最大限度地减少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_idfriend_id。每一行 在表格中基本上表示用户user_id已经与用户friend_id建立了联系。

    使用这样的表格,您甚至不必通过好友列表。你可以做一个INNER JOINuser_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;
}

它应该阐明如何选择正确的值并进行比较。