Счетчик онлайна на php с глюком

Dr.And

Новичок
Помогите пожалуйста, кто силен в php, подскажите, что в коде не так.
Я нашел готовое решение - Счетчик онлайна на php без использования БД.
Работает более-менее нормально, но в логах на сервере видна ошибка в 16 строчке.
Код:
[Fri Jun 08 07:18:01 2012] [error] [client 62.109.7.ххх] PHP Notice:  Undefined variable: online_array
in /home/dr.and/data/www/ххх.com/counters/co_online.php on line 16, referer: http://www.xxx.com/.../page.php
Вот весь код:
Код:
<?php
$data="online.dat";
$time=time(); $past_time=time()-60;
header('Content-Type: text/html; charset=windows-1251'); 
$readdata=fopen($data,"r") or die("Не возможно открыть файл $data");
$data_array=file($data); fclose($readdata);
if (getenv('HTTP_X_FORWARDED_FOR')) $user = getenv('HTTP_X_FORWARDED_FOR');
else $user = getenv('REMOTE_ADDR'); $d=count($data_array);
for($i=0;$i<$d;$i++){list($live_user,$last_time)=explode("::","$data_array[$i]");
if($live_user!=""&&$last_time!=""): if($last_time<$past_time): $live_user=""; $last_time=""; endif;
if($live_user!=""&&$last_time!=""){ if($user==$live_user){ $online_array[]="$user::$time\r\n";}
else $online_array[]="$live_user::$last_time";} endif;}
if(isset($online_array)): foreach($online_array as $i=>$str){ if($str=="$user::$time\r\n"){ $ok=$i; break;}}
foreach($online_array as $j=>$str){ if($ok==$j) { $online_array[$ok]="$user::$time\r\n"; break;}} endif;
$writedata=fopen($data,"w") or die("Не возможно открыть файл $data"); flock($writedata,2);
if($online_array=="") $online_array[]="$user::$time\r\n"; foreach($online_array as $str)
fputs($writedata,"$str"); flock($writedata,3); fclose($writedata);
$readdata=fopen($data,"r") or die("Не возможно открыть файл $data"); $data_array=file($data); fclose($readdata);
$online=count($data_array); echo "Сейчас на сайте: ".$online." чел.";
?>
Для работы счетчика естественно должен быть еще файл "online.dat"
Пробовал в начале скрипта прописать $online_array=array(); - в ответ новая ошибка в логах:
Код:
[Fri Jun 08 09:56:37 2012] [error] [client 62.109.7.xxx] PHP Notice:  Undefined offset:  1 
in /home/dr.and/data/www/xxx.com/counters/co_online.php on line 9, referer: http://www.xxx.com/.../page.php
Можно было бы плюнуть на эти нотисы, но при онлайне на странице 70-80 и более заметны скачки в показателях счетчика.
Примерно так: 82 - 83 - 65 - 83 - 81 - 82 - 67 - 81 - 80
 

Semen

Семён
посмотри, что у тебя в "$data_array[$i]", похоже в строке нет "::"
 

Dr.And

Новичок
посмотри, что у тебя в "$data_array[$i]", похоже в строке нет "::"
В какой строке, этой?
PHP:
for($i=0;$i<$d;$i++){list($live_user,$last_time)=explode("::","$data_array[$i]");
Так стоит там "::" перед самим "$data_array[$i]", или вы что-то другое имеете ввиду?
 

Dr.And

Новичок
Попробовал на отдельной странице, выводит мой IP в таком виде - 77.87.159.xxx::1339148817
В таком же виде все IP пользователей сохраняются в файле .dat
 

Semen

Семён
ну значит в файле online.dat есть пустая строка
сделай так
PHP:
print_r($data_array);
 

Dr.And

Новичок
сделай так
print_r($data_array);
Получил такое значение: Array ( [0] => 77.87.159.xxx::1339151857 )
На счет пустой строки - периодически скачиваю во время погрешностей работы счетчика с сервера файл "online.dat" и там действительно
бывают пустые строки. Вот только почему они там появляются? Не должны ведь...
Разве что записи не корректно удаляются. Скажем в приведенном ниже примере мне не нравятся 2 записи, выделенные красным.
----------------
37.53.192.41::1339152672
92.252.219.73::1339152678
192.168.0.21, 95.54.248.91::1339152680
92.126.13.236::1339152680
178.214.193.2::1339152673
94.28.178.249::1339152674
77.87.159.152::1339152675
91.235.28.112, 80.239.242.190::1339152675
95.215.68.174::1339152675
----------------
to fixxxer
Поподробнее пожалуйста, я только недавно начал изучать PHP и суть вашего поста не совсем понимаю...
 

Dr.And

Новичок
Почитал. Откуда лабуда появляется тоже понял. Спасибо.
Из прочитанного следует, что в этих двух строках:
PHP:
if (getenv('HTTP_X_FORWARDED_FOR')) $user = getenv('HTTP_X_FORWARDED_FOR');
else $user = getenv('REMOTE_ADDR');
первая вообще не нужна.
Но с другой стороны представим ситуацию, что из локальной сети 2 пользователя одновременно заходят на одну страницу.
Тогда из 'REMOTE_ADDR' мы получим только 1 IP-адрес роутера, через который здание с локальной сетью подключено к интернету...
Но если прикинуть, что вероятность посещения 2-мя пользователями 1 страницы очень мала, то наверно вместо этих двух строк можно
просто написать:
PHP:
$user = getenv('REMOTE_ADDR');
хотя я попробовал - счетчик не работает. Закинул на сервер пустой файл online.dat, новые пользователи заходят, а счетчик показывает 1 чел. в онлайне...
 

Dr.And

Новичок
Хотелось бы воскресить тему.
Вот нашел еще один вариант, работает с сессиями. Но проблема в том, что в файле "base_sessions.dat"
появляются пустые строки и подсчет идентификаторов сессий идет с ошибками.
Вернее не пустые строки а куча пробелов в одной строке перед идентификатором.

s0k34bjf6vsu13jddse8im8vo2|1356014950
nkogriq3tcue2htkcmo19i3ou2|1356015110
(здесь куча пробелов) k0qnpari2vk22053hua63glhr0|1356015110
jpcpm1pil0jtot0b28f8m83vu6|1356015110
tmo9ua7utvlg4ialegu27tapd6|1356015110
hg69qmhghf3hmvjfmfnfp19cg1|1356015110

Может кто-то поможет найти причину появления пустых строк?
И собственно код счетчика:
PHP:
<?php
session_start();$id=session_id();
header('Content-Type: text/html; charset=windows-1251'); 
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))." чел.";
?>
 

Dr.And

Новичок
Пожалуйста
PHP:
<?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))." чел.";
?>
 

С.

Продвинутый новичок
Зачем создавать какую-то квази-сессию, если с точностью плюс/минус трамвайная остановка, все то же самое можно делать на стандартной сессии?
 

Dr.And

Новичок
Зачем создавать какую-то квази-сессию, если с точностью плюс/минус трамвайная остановка, все то же самое можно делать на стандартной сессии?
Код не мой, да и в php я не очень разбираюсь, только начал изучать. Сорри...
 

С.

Продвинутый новичок
Dr.And, что ты хочешь от форума? Только не надо говорить "помощи". Сформулируй четко и конкретно свой вопрос.
 
Сверху