Такс, ну что, продолжаю свою затею с рейтингом твиттерским. Сперва подитожу немного. Мы умеем выводить данные пользователя твиттера, мы имеем базу данных и у нас есть формуляр для регистрации новых участников. Что нам нужно ещё? Нужно, чтоб выводило этих пользователей, которые находятся в базе данных, и отсортировать их по числу фолловеров или числу сообщений. Между делом я расскажу о различиях рейтинга для Юкоз и отдельного рейтинга. Ну и под конец поговорим о косяках моего решения и о том, почему в ближайшем времени мой рейтинг не будет продвинут в массы. В начале я пытался сообразить объектно-ориентированный рейтинг, но с какого-то момента всё начинало упорно не работать и я решил отказаться от этой затеи. Сделал всё с функциями, да процедурами. Всех пользователей из рейтинга я запихал в массив и с этим массивом я сотворяю потом всякие извращения, типа, сортировки. Запрашиваем информацию из базы данных В начале нужно узнать, сколько пользователей твиттера участвует в нашем рейтинге. Для этого открываем базу данных и считаем записи с помощью функции count() и возвращаем это число. Code function get_count() { include ("db.php"); $db_count = mysql_query("SELECT count(*) FROM `user` WHERE activated = 1;", $db); $user_count = mysql_fetch_row($db_count); mysql_close($db); return $user_count[0]; } Кстати, я при каждом обращении к базе данных её заново открываю. Хорошо это или плохо, я не знаю. Я не настолько разбираюсь, чтобы сказать, лучше всё время держать базу данных открытой или, как я, открывать её только если нужно. Какой вариант больше в напряг серваку и мускулу, пока остаётся загадкой. Следующая функция сохраняет все записи из базы данных, которые были активированны (то есть, в поле activated стоит единичка), в двухмерном массиве. Как параметр передаём число участников из функции get_count. В одном поле записывается дата регистрации участника, во втором его ник в Твиттере. Весь этот массив возвращаем. Code function get_user_data($user_count) { include ("db.php"); $result = mysql_query("SELECT regdate, username FROM `user` WHERE activated = 1;", $db);
for($i = 0; $i < $user_count; $i++) { $userdata = mysql_fetch_row($result); $rec['date'][$i] = $userdata[0]; $rec['name'][$i] = $userdata[1]; } mysql_close($db); return $rec; } Сортировка массива Следующая функция требует массив с участниками и их количество как параметры. Открывается XML-файл первого участника и следующего. Если у первого участника фолловеров больше, то меняем их местами. Делаем это на один раз реже, чем количество участников. Возвращаем отсортированный массив. Code function order_by_followers($rec, $user_count) { for($i = 0; $i < $user_count-1; $i++) { $c = $i + 1; $xml1 = load_xml($rec["name"][$i]); $xml2 = load_xml($rec["name"][$c]);
if( strcmp($xml1->statuses_count, $xml2->statuses_count) > 0 ) { $temp = $rec["name"][$i]; $rec["name"][$i] = $rec["name"][$c]; $rec["name"][$c] = $temp; $temp = $rec["date"][$i]; $rec["date"][$i] = $rec["date"][$c]; $rec["date"][$c] = $temp; } } return $rec; } Другой вариант рейтинга - отсортированный по количеству сообщений. В принципе таже самая функция, что и выше, только сравниваем другое свойство твиттерянина. Существует ещё одна разница. В первой функции сортировки я использовал функцию strcmp, а во второй strnatcmp. Почему в обоих вариантах не работала strcmp, я не догоняю. Но работать сортировка по сообщениям с ней решительно не хотела. Code function order_by_statuses($rec, $user_count) { for($i = 0; $i < $user_count-1; $i++) { $c = $i + 1; $xml1 = load_xml($rec["name"][$i]); $xml2 = load_xml($rec["name"][$c]);
if( strnatcmp($xml1->statuses_count, $xml2->statuses_count) < 0 ) { $temp = $rec["name"][$i]; $rec["name"][$i] = $rec["name"][$c]; $rec["name"][$c] = $temp; $temp = $rec["date"][$i]; $rec["date"][$i] = $rec["date"][$c]; $rec["date"][$c] = $temp; } } return $rec; } Вывод рейтинга на экран Теперь рассмотрим процедуру вывода информации об одном участнике рейтигна. (А разницу между функцией и процедурой знаете? Функция возвращает что-нибудь и может использоваться как выражение. Процедура ничего такого не делает.) Ничего сложного тут нет, передаётся участник и индекс в массиве. Так как индекс начинается с нуля, прибавляем единицу - это место участника в рейтинге. Ну а остальные функции выводят аватар, ник, описание, количество фолловеров и сообщений, с чем я в самом начале разобрался. Code function print_user_data($user, $i) // выдаёт информацию об участнике { $с = $i + 1; $xml = load_xml($user); echo $с; print_avatar($xml); print_screen_name($xml); print_description($xml); print_followers_count($xml); print_statuses_count($xml); } print_all вызывается с параметрами массив с участниками и количество участников и в своё время вывзывает процедуру print_user_data столько раз, пока та не напечатает информацию обо всех участниках. Code function print_all($rec, $user_count) // выдаём всех участников { for($i = 0; $i < $user_count; $i++) { if(checklink($rec['name'][$i], 1, 0) == 1) { print_user_data($rec['name'][$i], $i); } else { } } } Разница версии для Юкоза от отдельного рейтинга - работа с session Вначале я разработал такую версию: В индексе один раз делался запрос в базу данных, который сохранялся в глобальной переменной $_SESSION["userdata"]. К слову, если на сайте нужно что-то с авторизацией пользователя, то эта переменная как раз и нужна. Она единственный мене на данный момент известный вариант сохранить информацию после перехода на другую страницу. Если эта переменная уже существует при вызове индекса, то данные брались оттуда, а не из базы данных. Code session_start();
if(isset($_SESSION["userdata"]) ) { $user_count = $_SESSION["count"]; $rec = $_SESSION["userdata"]; for($i = 0; $i < $user_count; $i++) { echo $rec['date'][$i]." ".$rec['name'][$i]." "; } }
if(!isset($_SESSION["userdata"]) ) { include("func.php"); $user_count = get_count(); $rec = get_user_data($user_count); for($i = 0; $i < $user_count; $i++) { echo $rec['date'][$i]." ".$rec['name'][$i]." "; } $_SESSION["userdata"] = $rec; $_SESSION["count"] = $user_count; } Для сортировки массива с пользователями вызывались отдельные скрипты. Они брали информацию из session, обрабатывали её и сохраняли в той же переменной. После сортировки они перенаправляли на главную страницу, на которой изображался уже обновлённый рейтинг. Если session нет, то они просто перенаправляют на главную. Code session_start();
if(isset($_SESSION["userdata"]) ) { include ("func.php"); $user_count = $_SESSION["count"]; $rec = $_SESSION["userdata"]; $rec = order_by_followers($rec, $user_count); for($i = 0; $i < $user_count; $i++) { echo $rec["date"][$i]." ".$rec["name"][$i]." "; } $_SESSION["userdata"] = $rec; header("Location: index.php"); }
if(!isset($_SESSION["userdata"]) ) { header("Location: index.php"); } Code session_start();
if(isset($_SESSION["userdata"]) ) { include ("func.php"); $user_count = $_SESSION["count"]; $rec = $_SESSION["userdata"]; $rec = order_by_statuses($rec, $user_count); for($i = 0; $i < $user_count; $i++) { echo $rec["date"][$i]." ".$rec["name"][$i]." "; } $_SESSION["userdata"] = $rec; header("Location: index.php"); }
if(!isset($_SESSION["userdata"]) ) { header("Location: index.php"); } Но для Юкоз мене пришлось придумывать другой вариант. При импорте этого кода на сайт при переходе по любой ссылке, на любой скрипт и т. д., открывалось новое окно. Пробовал прописывать в ссылках атррибут _self и _parent, но без толку конечно. Пришлось немножко изменить рейтинг. Теперь я не импортирую код, а открываю скрипт во фрейме. Вместо одного индекса и двух скриптов с редиректом, получились две просто страницы. Без session, а с постоянными запросами к базе данных. Все получилось намного короче. При открытии рейтинга отображается топ по фолловерам. Сперва берётся количество участников из базы данных, информация о них, массив с участниками сортируется и выдаётся. Code $user_count = get_count(); $rec = get_user_data($user_count); $rec = order_by_followers($rec, $user_count); print_all($rec, $user_count); Страница, с сортировкой по количеству сообщений, отличается лишь одной строкой. Вместо $rec = order_by_followers($rec, $user_count) там стоит $rec = order_by_statuses($rec, $user_count). Косяки 0. Когда в рейтинге будут тысячи участников, нужно будет их выводить не на одной странице, а разбивать по 10 или 20 участников на страницу. В принципе это не косяк, просто я ещё не взялся за решение этой проблемы, а делать это определённо придётся. 1. После всего этого стало очевидно, что в отдельной версии я могу себе позволить намного больше, чем при интеграции на этот сайт. Отдельный скрипт с приминением session намного элегантней. Когда я доведу мой рейтинг до ума, я поставлю его на отдельный домен, а не пристрою к этому сайту. На realonlinemoney.ru будет укороченная версия с возможностью подключиться к рейтингу. 2. Я не знаю, как быть с базами данных, как уменьшить нагрузку и всё такое. Оставить как есть, чтоб каждый раз скрипт подключался к базе данных, или же переделать, чтоб соединение открывалось только один раз. 3. И самый большой косяк, количество обращений к Twitter API, вроде, ограничено. Если количество подключений превышено, то вместо рейтинга вылазит куча ошибок PHP, потому что скрипт не может открыть XML-файлы с информацией пользователей. Как решить эту проблему? Сохранять всю информацию о каждом участнике в базу данных. Пожалуй, придётся. И придётся эти данные обновлять. Я не знаю ещё, как я это сделаю - будет администратор рейтинга базу данных вручную обновлять, или это будет происходить автоматов, скажем, раз в сутки. А может лучше дать пользователю возможность обновлять информацию о себе, чтобы заставить его после подключения к рейтингу иногда возвращаться на сайт. Но для этого уже конкретную авторизацию пользователя надо прикрутить. Ещё подумаю, короче. Ну и под конец приветствую первого участника моего Твиттер-рейтинга - Вадим Клименко. Конечно первый участник рейтинга - это я, но он был первым, кто сам зарегистрировался. Он ведёт свой блог на Юкозе и имеет какое-то отношение к Ю.Блогам. Кто он там, не знаю, но по крайней мере, когда я зарегистрировался там, письмо о том, что мой блог был добавлен, пришло именно от него. И когда я переписывался с поддержкой проекта, отвечал он. По ходу он пахан ихний, ну, или особа, приближенная к императору. 
|