Помогите пожалуйста, кто силен в php, подскажите, что в коде не так. Вот нашел один вариант (код не мой), работает с сессиями. Но проблема в том, что в файле "base_sessions.dat" появляются пустые строки и подсчет идентификаторов сессий идет с ошибками. Вернее не пустые строки а куча пробелов в одной строке перед идентификатором. Код (Text): s0k34bjf6vsu13jddse8im8vo2|1356014950 nkogriq3tcue2htkcmo19i3ou2|1356015110 (здесь куча пробелов) k0qnpari2vk22053hua63glhr0|1356015110 jpcpm1pil0jtot0b28f8m83vu6|1356015110 tmo9ua7utvlg4ialegu27tapd6|1356015110 hg69qmhghf3hmvjfmfnfp19cg1|1356015110 А поскольку показатели каждые 10 сек. обновляются аяксом, то на странице показатели счетчика "прыгают". Может кто-то поможет найти причину появления этих пробелов? И собственно код счетчика: Код (Text): <?php session_start(); //выделяем уникальный идентификатор сессии $id = session_id(); if ($id!="") { //текущее время $CurrentTime = time(); //через какое время сессии удаляются $LastTime = time() - 60; //файл, в котором храним идентификаторы и время $base = "base_sessions.dat"; $file = file($base); $k = 0; for ($i = 0; $i < sizeof($file); $i++) { $line = explode("|", $file[$i]); if ($line[1] > $LastTime) { $ResFile[$k] = $file[$i]; $k++; } } for ($i = 0; $i<sizeof($ResFile); $i++) { $line = explode("|", $ResFile[$i]); if ($line[0]==$id) { $line[1] = trim($CurrentTime)."\n"; $is_sid_in_file = 1; } $line = implode("|", $line); $ResFile[$i] = $line; } $fp = fopen($base, "w") or die ("Нет доступа к базе данных"); for ($i = 0; $i<sizeof($ResFile); $i++) { fputs($fp, $ResFile[$i]); } fclose($fp); if (!$is_sid_in_file) { $fp = fopen($base, "a"); $line = $id."|".$CurrentTime."\n"; fputs($fp, $line); fclose($fp); } } echo "Сейчас на сайте: ".sizeof(file($base))." чел."; ?>
гибельная технология ) каждые 10 сек читать/писать в файл каждым клиентом это не тру вэй. да еще без блокировки. если разобраться, раз уж ты открываешь сессию, то у тебя УЖЕ есть вся информация: в папке из настройки session.save_path лежат сессионные файлы. по одному на каждое подкючение. смотри время последнего изменения каждого файла и делай выводы. справка по php подскажет тебе все недостающие детали.
Блокировку добавить можно (в закоментированном виде добавил)... Но это не решает проблемы... Код (Text): session_start(); //выделяем уникальный идентификатор сессии $id = session_id(); if ($id!="") { //текущее время $CurrentTime = time(); //через какое время сессии удаляются $LastTime = time() - 60; //файл, в котором храним идентификаторы и время $base = "base_sessions.dat"; $file = file($base); $k = 0; for ($i = 0; $i < sizeof($file); $i++) { $line = explode("|", $file[$i]); if ($line[1] > $LastTime) { $ResFile[$k] = $file[$i]; $k++; } } for ($i = 0; $i<sizeof($ResFile); $i++) { $line = explode("|", $ResFile[$i]); if ($line[0]==$id) { $line[1] = trim($CurrentTime)."\n"; $is_sid_in_file = 1; } $line = implode("|", $line); $ResFile[$i] = $line; } $fp = fopen($base, "w") or die ("Нет доступа к базе данных");/* flock($fp,2); */ for ($i = 0; $i<sizeof($ResFile); $i++) { fputs($fp, $ResFile[$i]); } fclose($fp); if (!$is_sid_in_file) { $fp = fopen($base, "a"); $line = $id."|".$CurrentTime."\n"; fputs($fp, $line);/* flock($fp,3); */ fclose($fp); } } echo "Сейчас на сайте: ".sizeof(file($base))." чел.";
откуда ей взяться то? у тебя будет 3 поля: id - session_id - date_time тут пробелам взяться неоткуда...
этот скрипт в принципе не стоит отлаживать. дичь просто. скачай любой движок форума и поищи там слово online — технология отлажена отцами и дедами ))) Добавлено спустя 2 минуты 8 секунд: суть сводится к одному запросу: SELECT count(*) FROM `online` WHERE `last_activity` > :t базы данных такие базы данных!
У меня сайт с онлайн радио, люди долго сидят на страницах, поэтому `last_activity`в пролете. Именно поэтому и обновляю сам скрипт аяксом, что бы имитировать активность пользователя.
А с базами данных я никогда не работал, надо еще изучить матчасть А если бы умел сделать, как вы предлагаете - то бесспорно устроило бы...
когда-то надо начинать. сам понимаешь, без баз никуда! пробуй, а мы поможем. я бы посоветовал отложить строительство велосипедов ненадолго. таки возьми движок форума и покопайся во внутренностях. найдешь много полезного.
Скачал, лезу ковырять код... Добавлено спустя 21 минуту 49 секунд: Блин, нифига наковырять не могу. Наверно проще на free-lance.ru обратиться...
рефакторинг Код (PHP): session_start(); $base = "base_sessions.dat"; //файл, в котором храним идентификаторы и время $LastTime = time() - 60; //через какое время сессии удаляются touch($base); $file = file($base); $id = session_id(); //выделяем уникальный идентификатор сессии if ($id!='') { $ResFile = array(); foreach($file as $line) { list($sid, $utime) = explode('|', $line); if ($utime > $LastTime) { $ResFile[$sid] = trim($sid).'|'.$utime.PHP_EOL; } } $ResFile[$id] = trim($id).'|'.time().PHP_EOL; file_put_contents($base, $ResFile, LOCK_EX); $file=$ResFile; } echo "Сейчас на сайте: ".sizeof($file)." чел.";
Спасибо. Код работает, записывает идентификаторы сессий в файл через строчку. Но случается, что между идентификаторами пустой строчки нет и опять подсчет не корректный. Как следствие - те же "скачки" показателей счетчика... Пример записей в файле .dat k5kosmssqce1g9um2ihc08gqv6|1356080571 q3df1lnscdgltbka9jt1au25o7|1356080571 7p1ufgaia5i1vuqsoa3tv825h7|1356080571 t98hg3cs4cihtcq8j8ffj7g7q2|1356080571 443127n9gbnncvb9hlg444ff87|1356080571 7vtn09a2mk7u5q9lid9ntb77g5|1356080578 naf7cbpajou2fg2a6ftvqgkio0|1356080571 j4g66hf4i9fakrookrvjv1fn96|1356080571 elpvcvf4vi4cg0fdg2b2r747p2|1356080572 ibdmdkqbl4dfs1d0gud8cfd9m7|1356080572 p59fgemlih4ep7vnv6hvh7lah1|1356080572
замените $ResFile[$sid] = trim($sid).'|'.$utime.PHP_EOL; на $ResFile[$sid] = trim($sid).'|'.trim($utime).PHP_EOL; Добавлено спустя 1 минуту 12 секунд: писал на коленке. интерпретировал в голове) похоже упустил и пролезают лишние переводы строк
Идентификаторы стали писаться в файл уже по порядку, пустых строк нет. Но показатели счетчика по-прежнему "прыгают". Возможно это происходит из-за не корректной блокировки во время одновременного доступа к файлу .dat При онлайне 30-40 чел. - все нормально, но толко онлайн доходит до 100 и дальше - начинаются "прыжки".
OK, раз вы такие упертые, вот вам моя версия БЕЗ использования базы. Технология как я выше описал. Это ajax-скрипт, который должен вернуть "онлайн 2 пользователя". ajax.php Код (PHP): <?php session_start(); $dir = ini_get('session.save_path'); $now = time(); $timeout = 60; $_SESSION['var'] = $now; // just write simething to THIS session file $count = 0; foreach (glob($dir . '/sess_*') as $filename) { if (filemtime($filename) > ($now - $timeout)) { ++$count; } } echo "Online: {$count} user(s)"; Это произвольная страничка, из которой есть обращение к нашему скрипту, index.html Код (Text): <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Simplified example of "Users online"</title> <script src="/js/jquery.js"></script> <script> $(document).ready(function () { var info = $('#info'); function getAndShowCount() { $.get('/ajax.php', function(data) { info.html(data) }); } setInterval(getAndShowCount, 10000); }); </script> </head> <body> <h1>Hello!</h1> <p id="info">Wait...</p> <p id="lorem"> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris nec nisi leo, at rutrum nulla. </p> </body> </html>
Спасибо. Ваш способ для показа онлайна на всем сайте - работает на ура. Только вот похоже данные он берет с папки /var/www/user/data/mod-tmp, где лежат идентификаторы всех пользователей сайта. Мне же надо показывать онлайн на определенных страницах сайта по отдельности. Каким образом я смогу узнавать на какой странице сидит пользователь определенной сессии ?... Не удивляйтесь, если я с вашей точки зрения пишу ересь, я самоучка и далеко не все понимаю... Опыт и умения приходят со временем.
пытаюсь забукмарить вариант artoodetoo viewtopic.php?f=2&t=43048&sid=f32db7dd6df0b797cbb4f9542f8daa72#p344345 прикольно, как мне показалось, попробовал локально, все гуд, но на серваке... Код (Text): $dir = ini_get('session.save_path'); // /var/lib/php5 при этом Код (Text): var_dump (glob($dir . '/sess_*')); // bool(false) устанавливаю папке принудительно Код (Text): session_save_path("/tmp"); имеем 54 элемента массива, но они все с одним временем 1355349548 где косячу?
чтение каталога с файлами сессии имеет ряд недостатков. 1. там может лежать очень много файлов, так как сборщик удаляет файлы с определенной вероятностью. и скрипт будет каждый раз лопатить эти сотни или даже тысячи файлов. очень неоптимально 2. настройки сессии могут разниться от сервера к серверу. например есть понятие "глубина размещения файлов" , тогда надо будет лопатить рекурсивно еще и поддиректории.. для каждого запроса 3. посчитать просто кол-во онлайн юзеров только полбеды. зачастую нужно отображать их список(логинов) да еще посчитать гостей(незалогиненных). тут это вообще нереализуемо в общем хлипкое решение. тогда уж лучше в БД или в всеже в файле
Самым правильным решением будет удалить к черту счетчик с сайта и не парить мозг ни себе, ни форумчанам.
я просто разминался пример не претендует ни на что. разве что он получше онанизма с впиливанием строчек в единый файл. однозначно БД подойдет лучше. 1. это ты от меня узнал? заодно можно собрать мусор. +файловая система кешируется операционкой (поэтому сессии не так сильно тормозят как должны по идее). 2.это какая-то совсем гипотетическая возможность, стандартный сборщик мусора кажется не умеет с этим работать. я не видел ни разу. 3. согласен. но не будем бежать впереди топикстартера.