Использование FQL для получения только предстоящих дней рождения из API Facebook

Используя информацию о FQL и таблица пользователей из документации разработчика Facebook, я придумал следующий код.

    //build fql string
    $fql = "SELECT name, birthday_date FROM user 
              WHERE uid IN
                (SELECT uid2 FROM friend WHERE uid1 = me())
              AND strlen(birthday_date) != 0 AND substr(birthday_date,0,3) 
            IN ('{$currentMonth}/', '{$nextMonth}/')";
    $fql.=$orderBy;
    $fql.=" LIMIT " . $limit;

    //query facebook
    $params  =   array(
                 'method'    => 'fql.query',       
                 'query'     => $fql,
                 'callback'  => ''     
                  );
    $birthdays  =  $this->facebook_obj->api($params);

$currentMonth и $nextMonth задаются строковыми представлениями текущего и следующего месяцев соответственно в формате мм. (например, «09», «10» и т. д.)

Это «работает», но предположим, что сегодня 29 ноября, у меня 20 друзей, день рождения которых приходится на ноябрь, а $limit установлено на 10. В этом случае есть очень хороший шанс, что все 10 дней рождения, которые он возвращает, будут раньше. 29 ноября.

Что я действительно хотел бы сделать, так это получить предстоящие дни рождения с сегодняшнего дня, в этом месяце и в следующем. Как я могу изменить этот запрос, чтобы выполнить это?

Спасибо!

** Редактировать, см. ветку комментариев между Шоном и мной для возможных альтернативных решений. Ответ еще не принят, поскольку ни один из них напрямую не касается исходного кода/вопроса.


person sanukcm    schedule 04.11.2011    source источник


Ответы (3)


Это с опозданием на несколько месяцев, но, возможно, помогает другим людям, столкнувшимся с той же проблемой. По сути, оператор FQL IN проверяет не то, находится ли значение в заданном диапазоне, а то, соответствует ли данное значение любому из предоставленных различных значений. В вашем примере, если значения «09» и «10» являются значениями, то возвращаются все дни рождения в сентябре и октябре, поскольку эти месяцы рождения соответствуют указанным номерам месяцев.

Что вы можете сделать, так это рассчитать следующие значения с помощью PHP или любого другого языка, который вы используете, и использовать их в своем FQL (сегодня 17 марта, и мы хотим, чтобы 17 апреля было датой окончания):

  • Сегодняшний день месяца (17),
  • Сегодняшний месяц года (03)
  • Дата окончания день месяца (17)
  • Дата окончания месяц года (04)

Убедитесь, что дни и месяцы отформатированы с использованием дд и мм соответственно (дополнены нулем в случае одиночных цифр). Тогда ваш FQL будет выглядеть так:

      SELECT name, birthday_date
      FROM user 
      WHERE uid IN (SELECT uid2 FROM friend WHERE uid1 = me())
      AND strlen(birthday_date) != 0
      AND ((substr(birthday_date, 0, 2) = '03'
      AND substr(birthday_date, 3, 5) >= '17')
      OR (substr(birthday_date, 0, 2) = '04'
      AND substr(birthday_date, 3, 5) < '17'))
      ORDER BY birthday_date

Это вернет друзей, чей день рождения приходится на период с 17 марта по 17 апреля.

person vahidg    schedule 17.03.2012

AND created_time > strtotime('now') AND created_time < $endofnext

обратитесь к примерам @ http://www.php.net/manual/en/function.strtotime.php#97025

использование «сейчас» вернет текущее дневное время.


Эта функция вернет последний день следующего месяца, независимо от того, какой это месяц.

<?php 
/* $now can be set to any strtotime(), yesterday, last month, last year etc; */
$now = "now"; 
function EndOfNext($now){
    function lastDayOfMonth($month = '', $year = '') 
    { 
       if (empty($month)) { 
          $month = date('m'); 
       } 
       if (empty($year)) { 
          $year = date('Y'); 
       } 
       $result = strtotime("{$year}-{$month}-01"); 
       $result = strtotime('-1 second', strtotime('+1 month', $result)); 
       return date('m/d/y', $result); 
    } 
    function addRealMonth($timeStamp) 
    { 
        $tempMonth = date('m', $timeStamp); 
        $tempYear  = date('Y', $timeStamp); 
        if($tempMonth == "12") 
        { 
            $tempMonth = 1; 
            $tempYear++; 
        } 
        else 
            $tempMonth++; 

        $newDate = lastDayOfMonth($tempMonth, $tempYear); 
        return strtotime($newDate); 
    }
    $newChargeDate = strtotime($now); 
    $newChargeDate = addRealMonth($newChargeDate); 
    return date("m/d/y", $newChargeDate); 
}
$endofnext = EndOfNext($now);
echo $endofnext;
?>
person Shawn E Carter    schedule 04.11.2011
comment
Шон, большое спасибо за ответ. Однако мое понимание оператора FQL IN заключается в том, что использование точных дат вернет только дни рождения, которые приходятся на эти точные даты... другими словами, сегодня и в последний день следующего месяца. Это я перепутал? Можете ли вы указать диапазон, указав две даты? В моем исходном запросе я получаю все даты, поле месяца которых соответствует месяцам, которые я запрашиваю. Если я отправлю точные даты, я полагаю, что он вернет только дни рождения, соответствующие этим точным датам... В любом случае, я попробую это и посмотрю, что он возвращает! Спасибо! - person sanukcm; 04.11.2011
comment
используете ли вы с = и до = до, с тех пор (временная метка unix или любая дата, принятая strtotime): graph.facebook.com/search?until=yesterday&q=orange - person Shawn E Carter; 04.11.2011
comment
Я использую fql через FB API, как показано в моем коде выше, но использование since and until похоже, что это может быть лучшим решением! Либо так, либо я просто возьму имеющийся у меня набор результатов и пройдусь по нему с помощью PHP, чтобы удалить даты до сегодняшнего дня, используя date('d') или подстроку strtotime('now'). +1 за альтернативное решение. - person sanukcm; 04.11.2011
comment
вы можете использовать такие операторы, как ‹ › меньше и больше, чем с fql. - person Shawn E Carter; 04.11.2011
comment
я не уверен, сможете ли вы использовать с и до сих пор, поскольку fql все еще портируется для Graph API, поэтому позвольте мне отозвать это утверждение. - person Shawn E Carter; 04.11.2011

Вы также можете позволить FQL сделать за вас некоторую работу, например:

SELECT uid, name, birthday_date, strtotime(substr(birthday_date, 0, 5)) > now()
FROM user
WHERE uid in (SELECT uid2 FROM #freunde)
AND birthday_date <> ''
AND strpos(birthday_date,'06') = 0
ORDER BY substr(birthday_date, 0, 5)

возвращает поле логического типа «anon», указывающее, нужно ли вам включить этот результат в список отображения (true) или день рождения для этого пользователя уже находится в прошлом (false). К сожалению, я не смог заставить это предложение работать как предложение WHERE - продолжайте получать ошибку, но хотел бы знать, если кому-то повезло больше, чем мне.

  "error": {
    "message": "Call to a member function on a non-object", 
    "type": "BadMethodCallException"
  }
person Hugo Stieglitz    schedule 15.06.2012