I am trying to search a user's Facebook friends list against entries in a gamers table in an application database.
The gamers table looks like id, name, points. Eg. g_id-234567, name-john Smith, points-45. In this table a person's id, is actually their Facebook id.
I am using the following code in my Codeigniter application with the Facebook php sdk to return list of friends for the logged in user.
$friends = $facebook->api('/me/friends');
foreach ($friends["data"] as $value) {
echo $value['id'];
}
This code is in my index function of my controller, and it successfully echos the ids of all the friends of the logged in user.
How do I check if any of my Facebook friends id matches that of any gamer g_id in my gamers table.
I want to get the list of gamers who are my Facebook friends, and order this list in descending order of points witha limit of 20. This is to get the top 20 Facebook friends gamers.
I would like to use this list of the logged in user's top 20 Faccebook friends in my view.
Try this (If you are using mysqli)
$id = -1;
$list = array();
$stmt = $mysqli->prepare("SELECT * FROM gamers where id = ? ORDER BY points DESC LIMIT 20");
$stmt->bind_param("i", $id);
foreach($friends["data"] as $value) {
$id = $value['id'];
$stmt->execute();
$res = $stmt->get_result();
array_push($list,$res->fetch_row());
}
I hope, $list should contain the list of all facebook gamers.
Alternatively, you can use :
$friends_set = '(';
foreach($friends["data"] as $value) {
$friends_set .= $value['id'].',';
}
$new_set = preg_replace('/,$/',')',$friends_set);
$res = mysql_query("SELECT * from gamers WHERE id IN $new_set ORDER BY points DESC LIMIT 20");
while($row = mysql_fetch_array($res,MYSQLI_ASSOC) {
//do your stuff
}
Inside last loop you may traverse list of facebook gamers.
Related
I made page with all profiles. Every 3 rows I inserting a Premium block between results. I have 12 rows on page and 4 premium blocks between every 3 rows. I need to show random users with premium='1' row from mysql every foreach loop.
$sth = $db->prepare("SELECT count(*) as premiumCount FROM users WHERE premium='1'");
$sth->execute();
$answer = $sth->fetch();
$premium = $answer['premiumCount'];
$sth2 = $db->prepare("SELECT * FROM users WHERE active='1' AND block='0' ORDER BY premium DESC LIMIT 12");
$sth2->execute();
$result = $sth2->fetchAll();
foreach ($results as $answer) {
// getting user info
if ($premium > 0) {
$sth = $db->prepare("SELECT * FROM users WHERE premium='1' ORDER BY RAND()");
// getting premium user info
}
}
This code is work, but it can be 2-3 same premium blocks on page (I need 4 different blocks).
Select as many random premium users as you need before the loop with one query (you can add LIMIT 4 to your query) instead of selecting repeatedly inside the loop. That way you can be sure you won't have duplicates.
Fetch the results and store them in an array, and where you're running the "SELECT * FROM users WHERE premium='1'... query inside the loop, use a value from the array instead. You can use array_pop to get values so you won't have to mess with a counter or anything like that to keep track of your position in the array.
// getting premium user info
$sth = $db->prepare("SELECT * FROM users WHERE premium='1' ORDER BY RAND() LIMIT 4");
$sth->execute();
$premium = $sth->fetchAll();
foreach ($results as $answer) {
// getting user info
if ($premium) {
$premium_row = array_pop($premium);
}
}
Suppose there are 40 people on your web application and you are friends with only twenty of them. Each user has posted a photo and status update. How do you get the posts of the 20 people in your timeline all at once according to the time? What code will help?
What I did =
i fetched list of my friends using while loop and fetched their updates again using the while loop.
$get_users = $con->query("SELECT * FROM friends WHERE person1=$myid ");
while($rows=$get_users->fetch_assoc()){
$friendsid = $rows['person2'];
//this fetches 20 of my friends
//now what i did was fetching their updates using the WHILE loop again
$get_updates = $con->query("SELECT * FROM updates WHERE userid=$friendsid ");
while($rows=$get_updates->fetch_assoc()){
$updates_status = $rows['text'];
$updates_photo = $rows['photo'];
echo " $update_status <br> $updates_photo <br> ";
}
}
But the problem with this is, I always see the updates from my same friend first. Even if his update is 2 weeks old, it is shown at the very first whereas the 19th friend who updated his status just a minute ago is at the second last of the updates.
How do I get the updates according to the time posted from only my friends?
Please, use the code below:
$get_users = $con->query("SELECT * FROM friends WHERE person1=$myid ");
$friends = '';
while($rows=$get_users->fetch_assoc())
{
$friends .= $rows['person2'].',';
}
$get_updates = $con->query("SELECT * FROM updates WHERE userid IN ".substr($friends, 0, -1)." ORDER BY date"); //probably you have 'date' field
while($rows=$get_updates->fetch_assoc())
{
$updates_status = $rows['text'];
$updates_photo = $rows['photo'];
echo " $update_status <br> $updates_photo <br> ";
}
Your code is almost there. All you have to do to retrieve the latest 20 posts, you need to sort the data by your POST_TIME column. Something like this:
$get_users = $con->query("SELECT * FROM friends WHERE person1=$myid ");
while($rows=$get_users->fetch_assoc()){
$friendsid = $rows['person2'];
//this fetches 20 of my friends
//now what i did was fetching their updates using the WHILE loop again
$get_updates = $con->query("SELECT * FROM updates WHERE userid=$friendsid ORDER BY POST_TIME");
while($rows=$get_updates->fetch_assoc()){
$updates_status = $rows['text'];
$updates_photo = $rows['photo'];
echo " $update_status <br> $updates_photo <br> ";
}
}
Change POST_TIME with the proper column name.
i am a biginner in php and i have started building my project but this problem stops me ..
look at my function
my problem is i use load subjects in order in a page but after load it i need from each user to have 25 subjects if he/she have this ammount of subjects in DB to appear in the page in order so in my case some users have only one subject and the others have more than 25 subject then the user that have one subject if he is shown at the end of the page in first load of the page then the rest of the other subjects will be dessappear untill i press the view more btn
but acually what i need is to have orderd subjects as it is made by one user ? any help ??
:)
public static function getsubjects($users){
$output = array();
foreach ($users as $key => $fo){
$sql ="SELECT * FROM supject_content WHERE userid = '$fo->hostid' ORDER by subjectid DESC LIMIT 25";
$query= mysql_query($sql);
if($query){
if(mysql_num_rows($query)> 0){
while($row = mysql_fetch_object($query)){
$output[]=$row;
}
}
}
}
return $output ;
}
With the following code I get all the pages I admin on Facebook using FQL. I do not print them though.
$PageNames = $facebook->api('/fql', array('q' =>
'SELECT name, page_id FROM page WHERE page_id IN (
SELECT page_id FROM page_admin WHERE uid=me() )'));
Previously, I have added in my DB the *page_id* of some of my pages. My goal is to show the pages that I have not added to my DB yet. It is working correctly and the code is below.
foreach($PageNames['data'] as $PageName) {
$investigate_id = mysql_query("SELECT page_id FROM pages WHERE page_id='"
.$PageName['page_id']."' LIMIT 1 ");
if(mysql_num_rows($investigate_id) == 0) {
echo $PageName['page_id'].$PageName['name'];
}
}
My problem/question is if somehow I can avoid the numerous DB calls because it makes the query for every page I admin. How can I achieve this?
<?php
$IDs = array();
foreach($PageNames['data'] as $PageName){
$IDs[] = $PageName['page_id'];
}
$investigate_id = mysql_query('SELECT page_id FROM pages WHERE page_id IN (\''.implode('\', \'', $IDs)).' LIMIT 1 ');
while($assoc = mysql_fetch_assoc($investigate_id)){
// iff
}
?>
Using WHERE col IN will make one query will all ID so
WHERE page_id IN (1,3,45,6,7,6,7,5,2,1,5,76) and it will do it in query, just make the loop after over the results and do whatever you want !
You may collect the IDs from results you got with FQL and then query DB for rows that exists in results to filter those present in DB from results...
$fql = <<<FQL
SELECT name, page_id FROM page WHERE page_id IN (
SELECT page_id FROM page_admin WHERE uid = me()
)
FQL;
// Get results from API
$pages = $facebook->api('/fql', array('q' => $fql));
// Collect pages for later usage by ID
$pagesByIds = array();
foreach($pages['data'] as $page){
$pagesByIds[$page['page_id']] = $page;
}
// Query DB for all pages that exists in results
$pagesIds = implode(',', array_keys($pageByIds));
$res = mysql_query("SELECT page_id FROM pages WHERE page_id IN ({$pageIds})");
while($pageRow = mysql_fetch_assoc($res)){
$pageId = $pageRow['page_id'];
// Remove pages that present in API results and DB
if (isset($pagesById[$pageId])) unset($pagesById[$pageId]); ;
}
// Display details for pages not existing in DB
foreach ($pagesByIds as $page){
echo "ID: {$page['page_id']}, Name: {$page['name']} \n"
}
I'm wondering if this is the best way to tackle this issue. I am merging a Facebook users friends data, (from facebook - returns a multi array) with the votes from the users in that list that voted (from MySQL).
This is how I accomplished this. I'm a junior developer and looking for help on making my code as optimized as possible.
public function getFriendVotes(){
global $facebook;
// Get The users friends that use this app from facebook
$friends = $facebook->api_client->fql_query(
"SELECT uid, first_name, last_name
FROM user
WHERE uid IN (SELECT uid2 FROM friend WHERE uid1=$this->user)"
);
// Create an array of just the ids
foreach($friends as $friend){
$userids[] = $friend['uid'];
}
// Create a string of these ids
$idstring = implode(",", $userids);
// Get the votes from only the users in that list that voted
$result = $this->db->query(
"SELECT vote, userid FROM user_votes WHERE userid IN ($idstring)"
);
// Create a new result set (multi array). Include the data from the first
// Facebook query, but include only those who voted and append their votes
// to the data
$row = $result->fetch_assoc();
foreach($friends as $friend){
if($row['userid'] == $friend['uid']){
$return[$count] = $friend;
$return[$count]['vote'] = $row['vote'];
$row = $result->fetch_assoc();
$count++;
}
}
return $return;
}
I asume that fql_query does support mysql syntax and it would be more efficient to use LEFT JOIN instead creatig extra query, here is my version of your code:
public function getFriendVotes(){
global $facebook;
// Get The users friends that use this app from facebook
$friends = $facebook->api_client->fql_query("
SELECT DISTINCT u.uid,u.first_name,u.last_name
FROM user AS u
LEFT JOIN friend AS f ON uid=uid2
WHERE f.uid1='{$this->user}'
");
$arrayUsers = array();
// Create an array of just the ids
foreach($friends as $v){
$arrayUsers[$friend['uid']] = $v;
}
unset($friends);
// Create a string of these ids
$idstring = implode(",", array_keys($arrayUsers));
// Get the votes from only the users in that list that voted
$result = $this->db->query(
"SELECT vote, userid FROM user_votes WHERE userid IN ({$idstring})"
);
$result = array();
// Create a new result set (multi array). Include the data from the first
// Facebook query, but include only those who voted and append their votes
// to the data
while($v = $result->fetch_assoc())
{
if(isset($arrayUsers[$v['userid']])
{
$arrayUsers[$v['userid']] = $v['vote'];
$result[] = $arrayUsers[$v['userid']];
unset($arrayUsers[$v['userid']], $v);
}
}
return $return;
}
I can't tell you how your code would perform without measuring and testing. I would look for other issues with your code, that would make it a bit more readable/maintanable. For example:
Create smaller methods.
Inside the main method , I see some chunks of code that are well commented. Why not create a method instead of making a huge comment in the main method?
For example:
// Get The users friends that use this app from facebook
$friends = $facebook->api_client->fql_query(
"SELECT uid, first_name, last_name
FROM user
WHERE uid IN (SELECT uid2 FROM friend WHERE uid1=$this->user"
);
return $friends;
Would make an interesting
functin get_users_friends_from_facebook($facebook){
// Get The users friends that use this app from facebook
$friends = $facebook->api_client->fql_query(
"SELECT uid, first_name, last_name
FROM user
WHERE uid IN (SELECT uid2 FROM friend WHERE uid1=$this->user"
);
return $friends;
}
In the same manner,
// Get the votes from only the users in that list that voted
$result = $this->db->query(
"SELECT vote, userid FROM user_votes WHERE userid IN ($idstring)"
);
Is a good candidate to
function get_votes_from_voters(){
// Get the votes from only the users in that list that voted
$votes = $this->db->query(
"SELECT vote, userid FROM user_votes WHERE userid IN ($idstring)"
);
}
Give variables meaningful names to the context.
$return isn't a good name. Why don't you name it $users_votes for example?
Try to keep the naming convention of your plataform.
Check the apis you're using. Are they using camelCase? Are they using underscores? Try to keep with your libraries and plataform conventions. Check this topic for a good reference.
And welcome to SO. Your code is fine. Try to read some OO principles, you could even cut more lines of your code. All the simple advices I wrote here are avaiable in a great book named Code Complete.
I took points from all your comments and rewrote this method as below. Thanks for all the great input.
public function getAppUserFriends(){
global $facebook;
return $facebook->api_client->fql_query(
"SELECT uid, first_name, last_name
FROM user
WHERE uid IN (SELECT uid2 FROM friend WHERE uid1=$this->user)
AND is_app_user;"
);
}
public function getFriendVotes(){
// Get the users friends that use this app
$friends = $this->getAppUserFriends();
// Create an array with the ids as the key
foreach($friends as $v){
$arrayFriends[$v['uid']] = $v;
}
// Create a string of these ids
$idString = implode(",", array_keys($arrayFriends));
// Get the votes from only the users in that list that voted
$result = $this->db->query(
"SELECT vote, userid
FROM user_votes
WHERE pollid=$this->poll
AND userid IN ($idString)"
);
// Pluck out user data from facebook array where the user has voted
// and add the vote to that array
while($row = $result->fetch_assoc()){
$friendsVotes[$row['userid']] = $arrayFriends[$row['userid']];
$friendsVotes[$row['userid']]['vote'] = $row['vote'];
}
return $friendsVotes;
}
Are you having performance troubles in this method? Because unless you are, there's no need to optimize it.
Code first, profile the code, and then optimize where it does the most good.
$friends = $facebook->api_client->fql_query(
"SELECT uid, first_name, last_name
FROM user
WHERE uid IN (SELECT uid2 FROM friend WHERE uid1=$this->user"
);
could probably be shortened to
$userids = $facebook->api_client->fql_query(
"SELECT uid
FROM user
WHERE uid IN (SELECT uid2 FROM friend WHERE uid1=$this->user)"
);
because the uid is the only thing you seem to be using from fb
It was a little hard for me to tell what you are trying to do, but you might consider looking at PHP's array_intersect (and its cousins).
A = {1:'fred', 2:'bob'}
B = {1: 2, 3: 0}
C = array_intersect( array_keys(A), array_keys(B) )
D = {}
foreach (C as c) {
D[c] = (A[c], B[c])
}
The syntax is off there but I hope it leads you in the right direction.