Вопрос собственно к WRC. Ты ведь написал своё двигло под блог, скажи, как ты реализовал отлов повторных просмотров для постов? Я думаю сделать отдельную базу и вести учет айпишников. Хватит ли этого?
как ты реализовал отлов повторных просмотров для постов?
Собственно 2 решения я написал в своём блоге. Больше я ничего не придумал... у себя я в начале поставил отлов с помощью куков, но совершенно случайно обнаружил что в осле и опере это почему то не канает (я лазаю в мозилке)... и поэтому недавно поменял на сессии - хоть и не совершенно точно, но кроссбраузерно.
Quote (Aleko)
Я думаю сделать отдельную базу и вести учет айпишников.
Базу всего лишь для этого? бред... я даже для меню пожадничал базы... И потом... просмотры это то, чего может быть очень много. Больше всего остального... Лучше узнать как ограничить время жизни определённой сессии, а не всех как делает функция session_set_cookie_params() (перечитал весь нет, ничего стоищего не нашёл) Ну а если такого не возможно то валяй... делай базу айпишников. Этого вполне хватит, но задолбаешься делать...
Да нет, базу сделать просто. У меня сейчас около 20 сложно связанных таблиц и нормально, всё летает - главное не тупить с проектированием базы а делать по уму. Другое дело что лишние запросы это плохо. Сессиями я делать не хочу так как накрутить будет легко - сессия держится пока не закроется окно браузера, затем только кука висит, которую можно легко стереть. По этому и нужна база. Ты кстати используешь сессионные куки или свои вешаешь, например при входе на сайт?
<? function movies_stats_add($id){ if(!preg_match("/^\d+$/",$id)){return false;} if(isset($_SESSION['movies_stats_'.$id])){return false;} $_SESSION['movies_stats_'.$id]=''; require_once("sql.php"); mysql_query("UPDATE movies SET hosts=hosts+1 WHERE id=".$id); return true; }
echo movies_stats_add(1); ?>
Логика такова что просмотром считается открытие страницы материала в течении одной сессии. То есть если вы просмотрели новость, потом закрыли браузер, снова его открыли и ещё раз просмотрели новость то к новости прибавится соответственно 2 запроса, я считаю такие запросы "легальными". В итоге не нужно пасти ip адрес и ронять базу раз в сутки - полный дзен.
Дабы зря не грузить сервак сначала я проверяю $id материала, затем проверяю, не просматривал ли пользователь эту новость в течение текущей сессии и только потом подрубаюсь к базе, вешаю сессию и увеличиваю значение хостов на 1.
главное не тупить с проектированием базы а делать по уму.
Вот у меня была такая ошибка. Хотел как бы всё по быстрее сделать и сказать алилуя... А теперь каждый раз переписываю скрипт.
Quote (Aleko)
сессия держится пока не закроется окно браузера
Цитирую с сайта где я "учусь":
Quote
session_set_cookie_params(int lifetime [, string path [, string domain]]) - с помощью этой функции можно установить, как долго будет "жить" сессия, задав unix_timestamp определяющий время "смерти" сессии. По умолчанию, сессия "живёт" до тех пор, пока клиент не закроет окно браузера.
То есть если верить этому определению можно сменить метод сбрасывания сессии: закрытие браузера на время.
Quote (Aleko)
Ты кстати используешь сессионные куки или свои вешаешь, например при входе на сайт?
И расскажи ка мне что такое сессионные куки и свои вешалки, а то я знаю только сессии и куки
Quote (Aleko)
я сделал так:
Ну дак ведь моё решение на сессиях имеет такой же смысл.
Code
<?php session_start(); if(!$_SESSION['movies_stats_'.$id]){ require_once("sql.php"); mysql_query("UPDATE movies SET hosts=hosts+1 WHERE id=".$id); $_SESSION['movies_stats_'.$id] = 1; } ?>
Но проблема всё ещё остаётся. Этим методом так же можно набить просмотры, правда закрытием и открытием браузера
Сессии это те же самые куки. Прочитай про механизм сессий. Их жизнь обычно гарантируется до закрытия окна + несколько часов (в зависимости от настройки php.ini), именно поэтому я так и написал. Во время авторизации я вешаю свою куку дабы после перезагрузки компа пользователь не вводил логин и пароль заного. Могу выложить листинг моей авторзации.
Сессии это те же самые куки. Прочитай про механизм сессий.
Это я знаю. Вообще сессии произошли от куков.
Quote (Aleko)
Их жизнь обычно гарантируется до закрытия окна + несколько часов (в зависимости от настройки php.ini), именно поэтому я так и написал.
То есть ты намекаешь что сессия обрабатываются в браузере? А для чего тогда path? Вполне логично было бы сохранять туда сессии. Ну лично я так думаю, без всяких умных текстов
Quote (Aleko)
Во время авторизации я вешаю свою куку дабы после перезагрузки компа пользователь не вводил логин и пароль заного. Могу выложить листинг моей авторзации.
Нет. Не нужно. Я уже подозреваю какая у тебя там форма. Я что то подобное задумал для добавления комментов. А вот интересно, как на ucoz сделаны просмотры. Есть идеи? Всё таки на ucoz можно набивать просмотры, но очень очень постепенно. Допустим эту тему, я, в дальнейшем, раз десять уже посмотрел. Сейчас посмотрел и просмотр всё равно увеличился. Значит используется не база данных, а что то другое. Хотя не факт что их система работает на php.
Очень просто. За хост считается уникальный ip. При просмотре новости с уникального ip он пишется в sql базу вместе с id материала. После чего материалу плюсуется хост. Раз в сутки или около того сервер дропает базу ip адресов и хосты зачисляются по новой. Я практически уверен что всё именно так, отличие может быть в том что отлавливается не только ip но ещё скажем разрешение экрана - так обычно делают. почитай по запросам "подсчет хостов".
А я так не думаю. Я проверил во всех браузерах, и во всех на одну единицу хост повысился. Мож всё таки с браузером мутят? Ну ip уж точно отпадает. Ну если только они в базу ещё тип браузера забивают, тогда уж пусь, но зачем?
Лады... от дискуссий к делу. Я всё таки поменял своё отношение к базам, после того как придумал, как их можно легко удалять. Но всё же количество запросов резко увеличилось:
//избавляемся от просроченных эелементов mysql_query('DELETE FROM views WHERE delite_time<'.time());
//добавляем хост и элемент в views если в нём нет соответствующего элемента $views_result = mysql_query('SELECT * FROM views WHERE ip="'.$_SERVER['REMOTE_ADDR'].'" AND post_id='.$id); if(!$views_result){//не уверен что такое условие выдаст то что нужно но пусь пока так mysql_query('UPDATE blog SET reads=reads+1 WHERE id='.$id); mysql_query('INSERT INTO views (ip, post_id, delite_time) VALUES ("'.$_SERVER['REMOTE_ADDR'].'", '.$id.', '.(time()+86400).')'); //...+24 часа } ?>
Теперь остаётся думать как уменьшить количество запросов.
$views_result в твоем случае кстати всегда будет true. False будет только в том случае если с базой данных "физически" не удалось связаться. Нужно проверять так: mysql_rows_affected($views_result)!=0
<?php if (!$_SESSION['pbs'.$post['id']]) { mysql_query('UPDATE sd_posts SET post_view_count="'.($post['post_view_count']+1).'"WHERE id="'.$post['id'].'"'); $_SESSION['pbs'.$post['id']]=1; } ?>
Проверял локально работает нормально. Количество просмотров зачисляется таким мпособом: открыл браузер, просмотрел +1 к просмотру. Открыл с др. браузера тоже +1. Закрыл браузер открыл данный пост +1 к просмотрам.
Сообщение отредактировал Slimmi - Пятница, 23.07.2010, 06:29
Все варианты сходятся к одному. Думаю эта проблема решена. Меня волнует другае теперь проблема. Капча.. Я ща делаю капчу на основе kcapcha. У вас я вижу свои капчи. На какой основе они?
Всё просто... работать нужно с сессиями... с начало разберись с самим кодом (смысле тот случайный код что будет на картинке), а потом уже приступай к картинке... Скоро напишу пост в блоге про капчу: php + js)
Quote (Slimmi)
твой вариант работает корректно с сессиями
Лучше использовать пока это. На данный момент мне кажется что это самый качественный подсчёт хостов.
Это для mssql - другая программа) я юзаю mysql, как и ты)
Вот код моей капчи:
Code
<?
// Возвращает изображение с проверочным кодом и создает у текущего пользователя // сессионную переменную captcha с его копией. $width = 80; // Ширина изображения $height = 36; // Высота изображения $font_size = 11; // Размер шрифта $let_amount = 5; // Количество символов, которые нужно набрать $font = "captcha.ttf"; //Путь к шрифту $letters = array('2','3','4','5','6','7','8','9','A','a','w','v','B','C','D','E','F','G','H','K','L','M','N','P','R','S','T','U','X','Y','Z'); // используемые символы $colors = array("10","40","70","100","130","160","190"); // используемые цвета $linesnum = 4; // количество линий на изображении $dotsnum = 100; // количество точек на изображении
Вешаем сессию с кодоп капчи, посылаем форму с ней же пользователю и ждем ответа. Сверяем код возвратившийся от пользователя и код в сессии, если всё ок - идем дальше.
Aleko, ты ещё хотел написать код авторизации. Я примерно понимаю как это.. Но все же хочется взглянуть на готовую. Просто у меня будет админка и нужно к ней закрыть доступ
Ещё вопрос ты как ЧПУ делал? Все прописывал через .htaccess или передаешь параметры .htaccess с помошью php?
Важно очищать сессию после каждой проверки (неважно, успешной или нет). Не стоит полагаться на то, что при обновлении страницы скрипт картинки сгенерит новый текст — бот может просто не запрашивать картинку, а вводить один и тот же ответ, который в самом начале прочитал и сообщил боту сам злоумышленник.
Ну я со словом "резко" немного преувеличил) Сам посмотри как главная грузится и страница материала... Вроде страница немного медленнее, или это просто изо того что я так хочу думать. Показалось видать. Сделал так:
Code
mysql_query('DELETE FROM views WHERE delite_time<'.time()); $views_result = mysql_query('SELECT * FROM views WHERE ip="'.$_SERVER['REMOTE_ADDR'].'" AND post_id='.$full['id']); if(!mysql_result($views_result,0)){ mysql_query('UPDATE blog SET reads=reads+1 WHERE id="'.$full['id'].'"'); mysql_query('INSERT INTO views (ip, post_id, delite_time) VALUES ("'.$_SERVER['REMOTE_ADDR'].'", '.$full['id'].', '.(time()+86400).')'); }
WRC, ну во первых http://www.mysql.ru/docs/man/UNION.html почитай, пригодится, во вторых ты проверяешь старые записи каждый раз а мог бы раз в час хотя бы. В итоге будет 2 запроса вместо четырех:
Code
if(mysql_result(mysql_query("SELECT COUNT(*) FROM views WHERE ip='$_SERVER[REMOTE_ADDR]' AND post_id=$full[id]"),0) == 0){ // получаем количество строк mysql_query("begin"); // открываем поток mysql_query("UPDATE blog SET reads=reads+1 WHERE id=$full[id]"); mysql_query("INSERT INTO views (ip, post_id, delite_time) VALUES ('$_SERVER[REMOTE_ADDR]',$full[id],".(time()+86400).")"); mysql_query("commit"); // закрываем поток }
Slimmi, это ведь элементарные вещи, которые тебе уже давно должны сразу приходить в голову. Допустим материалы выводятся следующим циклом:
Code
while($date = аррэй(запрос)){ echo 'тратата'; }
Теперь добавим несколько переменных и условие к содержимому в цикле:
Code
$i = 0; $str = $_GET['str'];//с какого материала начинать $numstr = 5;//количество материалов на одной странице while($date = аррэй(запрос)){ $i++;//порядковый номер материала if($i>$str && $i<=($str+$numstr)){ echo 'тратата'; } //вводим в адр. строку index.php?str=5 и материалы будут //высвечиваться с порядковыми номерами от 6 до 10 }
Думаю понятно объяснил)
Сообщение отредактировал WRC - Пятница, 30.07.2010, 12:20