Объединение данных из двух разных наборов данных (Facebook и MySQL) - PullRequest
3 голосов
/ 10 ноября 2009

Мне интересно, если это лучший способ решить эту проблему. Я объединяю данные о друзьях пользователей Facebook (из facebook - возвращает несколько массивов) с голосами пользователей из этого списка, которые проголосовали (из MySQL).

Вот как я это сделал. Я младший разработчик и ищу помощь в создании максимально оптимизированного кода.

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;
}

Ответы [ 6 ]

2 голосов
/ 10 ноября 2009

Я взял очки за все ваши комментарии и переписал этот метод, как показано ниже Спасибо за отличный вклад.

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;
}
2 голосов
/ 10 ноября 2009

Я не могу сказать вам, как ваш код будет работать без измерения и тестирования. Я бы искал другие проблемы с вашим кодом, что сделало бы его немного более читабельным / доступным. Например:

Создание меньших методов.

Внутри основного метода я вижу несколько фрагментов кода, которые хорошо прокомментированы. Почему бы не создать метод вместо огромного комментария в основном методе?

Например:

// 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;

Было бы интересно

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;
}

Таким же образом,

// 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)"
);

Является хорошим кандидатом на

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)"
    );
}

Дайте переменным значимые имена контексту.

$return не хорошее имя. Почему бы вам не назвать это $users_votes например?

Постарайтесь придерживаться соглашения о присвоении имен вашей платформе.

Проверьте используемый API. Они используют camelCase? Они используют подчеркивание? Попытайтесь придерживаться своих библиотек и платформ. Проверьте эту тему для хорошей ссылки.

И добро пожаловать в ТАК. Ваш код в порядке. Попробуйте прочитать некоторые принципы ОО, вы можете даже сократить количество строк своего кода. Все простые советы, которые я написал здесь, доступны в большой книге под названием Code Complete .

2 голосов
/ 10 ноября 2009

Я предполагаю, что fql_query поддерживает синтаксис mysql, и было бы более эффективно использовать LEFT JOIN вместо создания дополнительного запроса, вот моя версия вашего кода:

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;
}
1 голос
/ 10 ноября 2009

У вас проблемы с производительностью в этом методе? Потому что, если вы не, нет необходимости оптимизировать его.

Сначала кодируйте, профилируйте код, а затем оптимизируйте, где он приносит наибольшую пользу.

0 голосов
/ 10 ноября 2009

Мне было немного сложно рассказать, что вы пытаетесь сделать, но вы могли бы рассмотреть возможность взглянуть на PHP array_intersect (и его кузены).

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])
}

Синтаксис там, но я надеюсь, что он ведет вас в правильном направлении.

0 голосов
/ 10 ноября 2009
$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"
);

может быть сокращено до

$userids = $facebook->api_client->fql_query(
  "SELECT uid
    FROM user
    WHERE uid IN (SELECT uid2 FROM friend WHERE uid1=$this->user)"
);

потому что uid - единственное, что вы, похоже, используете из fb

...