Объединение данных из двух разных наборов данных (Facebook и MySQL)

StackOverflow https://stackoverflow.com/questions/1704137

Вопрос

Мне интересно, является ли это лучшим способом решения этой проблемы.Я объединяю данные друзей пользователей 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;
}
Это было полезно?

Решение

Я предполагаю, что 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;
}

Другие советы

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

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

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

Например:

// 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?Используют ли они подчеркивания?Постарайтесь придерживаться соглашений о ваших библиотеках и платформах.Проверять Эта тема за хорошую ссылку.

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

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

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

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

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

$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 - это единственное, что ты, кажется, используешь с Facebook

Мне было немного сложно сказать, что вы пытаетесь сделать, но вы могли бы рассмотреть возможность просмотра 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])
}

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top