PHP (Статей: 62)

Для проекта нужно было разработать модуль авторизации с vkontakte.ru. После курения мануалов получилось очень даже неплохо. И так как увидел в блоге отминусованую статью (сабж), то решил написать самому.

Помолясь приступим smile

Шаг 1.
Создание приложения на сайте vk.com с последующей настройкой. Она несложная, нужно всего лишь прописать адрес сайта и базовый домен. Там же получаем защитный ключ и id приложения, которые будем использовать дальше.

Шаг 2.
На странице, на которой вы разместили кнопку авторизации(или ссылку, как в нашем примере), делаем так, чтобы при нажатии на нее нас перекинуло по адресу
http: //api.vk.com/oauth/authorize?client_id=ID&redirect_uri=REDIRECT&display=MODE
. Где ID - айди нашего приложения, REDIRECT - адрес скрипта - обработчика, MODE - режим отображения окна авторизации(page – форма авторизации в отдельном окне, popup – всплывающее окно, touch – авторизация для мобильных Touch-устройств , wap – авторизация для мобильных устройств с маленьким экраном или без поддержки Javascript). Это можно реализовать несколькими способами, но я напишу как делал сам.
<?php

$ID = ""; //наш Id приложения
$REDIRECT = ""; // адрес обработчика
echo "
<script>
function authVk(){
location.href = 'http://api.vk.com/oauth/authorize?client_id=".$ID."&redirect_uri=".$REDIRECT."&display=page';
}
</script>
<a href=\"#\" onclick=\"authVk();\" >Вконтакте</a>";
?>

Теперь нас при нажатии на ссылку переадресовывает туда куда нужно.

Шаг 3.

Создадим сам скрипт - обработчик, который будет работать непосредственно с пользователем, его данными и выполнять авторизацию.
<?php

$SECRET = ""; // секретный код, полученный в панели управления приложением на vkontakte
if ($code = $_GET['code']){
if($curl = curl_init()){
$St = 'https://api.vk.com/oauth/token?client_id='.$ID.'&code='.$code.'&client_secret='.$SECRET;
curl_setopt($curl,CURLOPT_URL,$St);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // только так можно "обуть" защищенный режим с помощью cUrl*a
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); // только так можно "обуть" защищенный режим с помощью cUrl*a
curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);

$stream = curl_exec($curl);
$data = json_decode($stream);

if($data->access_token){
$token = $data->access_token;
$userId = $data->user_id;                         // Id пользователя который авторизовался
}

if($curl = curl_init()){
$url = 'https://api.vkontakte.ru/method/getProfiles?uids='.$userId.'&fields=photo_big,sex,bdate,screen_name&access_token='.$token; // теперь можно воспользоваться методом getPrifiles, где параметр fields принимает значение всех необходимых вам от пользователя данных. 
curl_setopt($curl,CURLOPT_URL,$url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
$stream = curl_exec($curl);
$data1 = json_decode($stream);
$first_name = $data1->response[0]->first_name;    // получаем фамилию пользователя
$last_name = $data1->response[0]->last_name;      // получаем имя пользователя
$photo = $data1->response[0]->photo_big;          // получаем авку пользователя
$sex = $data1->response[0]->sex;                  // получаем пол пользователя
$bdate = $data1->response[0]->bdate;              // получаем дату рождения пользователя
$login = $data1->response[0]->screen_name;        // получаем логин пользователя
$first_name = iconv('UTF-8', 'windows-1251', $first_name);
$last_name = iconv('UTF-8', 'windows-1251', $last_name);
}
}
}
?>
Для лучшего закрепления информации о методе getProfiles, процитирую оф. документацию.

Возвращает информацию о пользователях в виде набора массива объектов, каждый из которых может иметь поля uid, first_name, last_name, nickname, sex, bdate (birthdate), city, country, timezone, photo, photo_medium, photo_big, photo_rec.
Если в параметре fields было указано поле contacts, то будут доступны также поля: home_phone, mobile_phone.
Если в параметре fields было указано поле education, то будут доступны также поля: university, university_name, faculty, faculty_name, graduation.
Если в параметре fields было указано поле counters, а в параметре uids задан только один идентификатор, то будет доступно поле counters в котором будет находится объект со счетчиками различных объектов у пользователя.
Значения uid, first_name и last_name возвращаются всегда, вне зависимости от выбранных полей и их количества.

Вот как-бы и все) И да, не забываем, что в настройках приложения нужно будет указать в форме "Адрес сайта" путь к обработчику, то есть site.ru/auth.php, к примеру.
Статью писал для своего сайта, но по некоторым причинам решил все свои статьи перезалить сюда (что бы не утерять)!

Чаще всего нам приходится хранить настройки в базе данных в таком виде:
+-------------------------+
| ключ  |  значение       |
|-------------------------|
| home  |  http://7je.ru  |
+-------------------------+
В итоге у нас выходит как минимум 30 значений!

Далее мы заносим эти значения в скрипте в массив!
Самый обоснованный вариант, это выглядет так:
<?php
$qury = mysql_query("SELECT `key`, `value` FROM `setting`;");

while ($row = mysql_fetch_array($qury, MYSQL_ASSOC)) {
    $_set[$row['key']] = $row['value'];
} 
?>
проверим это на оперативность при 10,000 записей!
Результат: 0.0095, 0.0144, 0.0219

В принципе так подумать, что же это за конфиги, в которых хранится 10,000 записей? но необходимо учитывать то, что у вас сидит на сайте ~1000 человек, каждый из них кликает по ссылкам периодичностью в 3 секунды.
каждый раз при генерации страницы для пользователя идет запрос в базу...
а это уже сказывается на сервере...

Я предлагаю кэшировать конфиги следующим образом:
<?php
$file = 'setting.cache.db';
$life = is_file($file) ? filemtime($file) + 43200 : 0;

if ($life < time()) {

    $qury = mysql_query("SELECT `key`, `value` FROM `setting`;");

    while ($row = mysql_fetch_array($qury, MYSQL_ASSOC)) {
        $_set[$row['key']] = $row['value'];
    }
	
    file_put_contents($file, serialize($_set), LOCK_EX);

} else {

    $_set = unserialize(file_get_contents('setting.cache.db'));

}
?>

Т.е мы проверяем когда было произведено последнее кэширование, и если это было 12 часов назад, то мы делаем запрос к бд, и записываем полученный массив в файл, или если время не истекло, то открываем файл, и заносим в переменную полученный массив.

В итоге выигрыш: 0.0019, 0.0023, 0.0037
Статью писал для своего сайта, но по некоторым причинам решил все свои статьи перезалить сюда (что бы не утерять)!

Думаю все видели во многих социальных сетях такую штуку как "События у друзей".
Я хотел бы показать простейшую реализацию данной задачи...

Для этого нам нужно создать три таблицы:
--
-- Список событий
--

CREATE TABLE IF NOT EXISTS `events` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL COMMENT 'Пользователь, чье событие.',
  `text` text NOT NULL COMMENT 'Описание события.',
  PRIMARY KEY (`id`),
  KEY `user_id` (`user_id`),
  FULLTEXT KEY `text` (`text`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=0;

--
-- Список друзей
--

CREATE TABLE IF NOT EXISTS `friends` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_one` int(11) NOT NULL COMMENT 'ID пользователя чей друг.',
  `user_two` int(11) NOT NULL COMMENT 'ID пользователя кто друг.',
  PRIMARY KEY (`id`),
  KEY `user_one` (`user_one`,`user_two`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=0;


--
-- Список пользователей сайта
--

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(15) NOT NULL COMMENT 'Имя пользователя',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=0;

С таблицами вроде все! Теперь перейдем программному коду:
<?php
/* * Подключаемся к базе данных. */
mysql_connect('localhost', 'user', 'pass');
mysql_select_db('events');
/* * Указываем кодировку utf8 по умолчанию. */
mysql_query('SET NAMES utf8');

Теперь можем приступить к запросу с необычной выборкой:
<?php
$query = mysql_query("SELECT e.`text`, u.`name`  
                     FROM `events` e, `users` u, `friends` f 
                     WHERE f.`user_one` = {$id} 
                     AND e.`user_id` = f.`user_two` 
                     AND u.`id` = f.`user_two` 
                     ORDER BY e.`id` ASC;");

И выводим результат выполнения запроса:
<?php
while ($row = mysql_fetch_assoc($query)) {
	echo 'Пользователь <b>'.$row['name'].'</b>, '.$row['text'].'<br />';
}

Вот что у меня получилось:

Пользователь Вася, Добавил комментарий
Пользователь Вася, Добавил фотографию
Пользователь Вася, Удалил комментарий
Пользователь Петя, Удалил фотографию
Статью писал для своего сайта, но по некоторым причинам решил все свои статьи перезалить сюда! (что бы не утерять)

В следствии новости от разработчиков php, о прекращении поддержки расширения MySQL в PHP, в массах начинающих разработчиков (пишущих свои творения на языке php) началась паника.
Для паники пока что нет поводов, полностью расширение планируют убрать в шестой ветке php, которая выйдет еще не скоро! а пока что: "По*** пляшем"! так что есть время хорошенько изучить PDO или MySQLi. Лично я советую PDO.

И так! Для начала хотелось бы указать какие методы нам понадобятся для работы с PDO:

Основной класс PDO:
PDO :: BeginTransaction - Начало транзакции.
PDO :: commit - Выполнить транзакцию.
PDO :: exec - Выполнить SQL выражения и возвращение количество задействованных рядов.
PDO :: lastInsertId - Возвращает идентификатор последней вставленной строки или последовательности значения.
PDO :: prepare - Готовит оператор для выполнения и возвращает объект оператора.
PDO :: query - Выполняет SQL запрос.
PDO :: quote - Экранирование спец символов для использования в запросе.

Представление подготовленных заявлений PDOStatement:
PDOStatement -> execute - Выполнение подготовленного заявления.
PDOStatement -> fetch - Выбирает следующую строку из результирующего набора.
PDOStatement -> fetchAll - Возвращает массив, содержащий все строки результирующего набора.
PDOStatement -> fetchColumn - Возвращает один столбец из следующей строки результирующего набора.

Это далеко не весь набор методов для работы с PDO, полный список вы можете посмотреть тут http://php.net/manual/en/book.pdo.php

Первое что нам необходимо, это подключится к базе данных:
<?php
/* Сервер на котором расположена база данных. */
$dsn  = 'host=localhost;';
/* Имя базы данных с которой работаем. */
$dsn .= 'dbname=testbase;';
* Номер порта локального сервера. */
$dsn .= 'dbport=3306;';

/* Указываем кодировку с которой работаем. */
$driver = array(PDO :: MYSQL_ATTR_INIT_COMMAND => 'SET NAMES `utf8`');

try {
    $dbh = new PDO($dsn, $login, $passwd, $driver);
} catch (PDOException $e) {
    echo $e -> getMessage();
}
?>
Начиная с PHP 5.3.6 можно указывать кодировку в конструкторе:
<?php
/* Сервер на котором расположена база данных. */
$dsn  = 'host=localhost;';
/* Имя базы данных с которой работаем. */
$dsn .= 'dbname=testbase;';
* Номер порта локального сервера. */
$dsn .= 'dbport=3306;';
* Указываем кодировку. */
$dsn .= 'charset=utf8;';

try {
    $dbh = new PDO($dsn, $login, $passwd);
} catch (PDOException $e) {
    echo $e -> getMessage();
}
?>
Теперь мы подключились, и можем работать с запросами!
Первое что нам понадобится, это добавление записей в базу данных:
<?php
$dbh -> exec("INSERT INTO `table` (`pole`) VALUES ('value');");

/* И сразу о применении lastInsertId() 
 * После добавления записи можно узнать id строки,
 * которую вы только что добавили.
 */
echo $dbh ->lastInsertId();
?>
А так же о пользе транзакций:

Транзакция - это группа последовательно выполняемых операторов SQL, которые либо должны быть выполнены все, либо не должен быть выполнен ни один из них. Главная задача транзакций - обеспечить целостность данных в случаях, когда несколько SQL-операторов выполняют зависящие друг от друга изменения данных.

Например нам необходимо выполнить INSERT INTO и UPDATE:

<?php
$dbh -> exec("INSERT INTO `privat` (`login`, `text`) VALUES ('Nu3oN', 'Hello');");
$dbh -> exec("UPDATE `users` SET `privat` = `privat` + 1 WHERE `user` = 'Nu3oN';");
?>
И как видим, если первый запрос не выполнится, то у пользователя все равно покажет что у него еще одно сообщение, хотя его не самом деле нет. Данный пример конечно не лучший, для показания плюса транзакций, но для обучения самое оно. Что бы не произошло такой ошибки, можно воспользоваться транзакциями:

<?php
try {
    $dbh -> beginTransaction();

    $dbh -> exec("INSERT INTO `privat` (`login`, `text`) VALUES ('Nu3oN', 'Hello');");
    $dbh -> exec("UPDATE `users` SET `privat` = `privat` + 1 WHERE `user` = 'Nu3oN';");

    $dbhh -> commit();
} catch(PDOException $e) {
    echo 'Ошибка при добавлении сообщения';
}
?>
Теперь получение информации:
<?php
// Непосредственно сам запрос:

$res = $dbh -> query("SELECT * FROM `table`;");

// Возможные способы представления информации:

/* Массив с числовыми ключами. */
$row = $res -> fetch(PDO :: FETCH_NUM);
/* Массив с ключами используемыми в названиях столбцов. */
$row = $res -> fetch(PDO :: FETCH_ASSOC);
/* Массив содержащий все строки в пределах запроса. */
$row = $res -> fetchAll(PDO :: FETCH_ASSOC);

/// Это можно использовать в циклах например.
while ($row = $res -> fetch(PDO :: FETCH_ASSOC)) {
    echo $row['pole'];
}

/// В примере с fetchAll можно так:
foreach ($row as $arr) {
    echo $arr['pole'];
}

// Выбор одной строки:

$res = $dbh -> query("SELECT `id` FROM `table` WHERE `pole` = 'value';");
$str = $res -> fetchColumn();
?>
В этом думаю ничего сложного нет...
Теперь я бы хотел рассказать о возможности запросов с подготовленным выполнением (prepare и execute):

Возможности запросов с заранее подготовленным выполнением:
- компилируется один раз, выполняется необходимое количество раз.
- четкое разделение между структурой и входными данными (предотвращение SQL инъекция).
- быстрое выполнение по сравнению с query()/exec(), даже для единичного выполнения.

Пример запроса:
<?php
$array = array(
               $_GET['value1'], 
               $_GET['value2']
              );

$stmt  = $dbh -> prepare("SELECT * FROM `table` WHERE `pole` = ? AND `pole2` = ?;");
$stmt -> execute($array);
$arr = $stmt-> fetchAll(PDO :: FETCH_ASSOC);
?>
Параметры для запроса могут быть даны в виде имен и быть привязаны к переменным:

<?php
$array = array(
               ':value'  => $_GET['value1'], 
               ':value2' => $_GET['value2']
              );

$stmt -> prepare('SELECT * FROM `table` WHERE `pole` = :value AND `pole2` = :value2;');
$stmt -> execute($array);
$arr = $stmt -> fetchAll(PDO :: FETCH_ASSOC);
?>
И на последок, для того что бы не писать каждый раз в таких методах как fetch() и fetchAll() способ извлечения (PDO :: FETCH_ASSOC, PDO :: FETCH_NUM и прочие), можно после подключения к базе указать способ по умолчанию PDO :: FETCH_ASSOC, а потом по необходимости уже указывать способы которые вам необходимы!

Например:
<?php
try {
    $dbh = new PDO($dsn, $login, $passwd, $driver);
    $dbh -> setAttribute(PDO :: ATTR_DEFAULT_FETCH_MODE, PDO :: FETCH_ASSOC);
} catch (PDOException $e) {
    echo $e -> getMessage();
}
?>
Спасибо за внимание, если что не понятно спрашивайте!
Статья подготовлена специально для http://www.7je.ru
-3
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Вот недавно столкнулся с такой проблемой.
У хостера выключена функция sеt_timе_limit(); и ехес();
а мне неохота лазить на хост и запускать крон.
Зашол в гугл искал искал и вот нарыл замечательный код.
<?php
ignore_user_abort(0);
@set_time_limit(0);
@ini_set('set_time_limit',0);
@ini_set('max_execution_time',0);
echo @ini_get('max_execution_time');
$in = 1*60*60; //спит 1 час
do
{
//здесь код на выполнение скрипта
sleep($in);//спит
}
while(true);
?>
и че я удивился, это то, что обошол этот запрет.
И функция у меня заработала.
Имейте ввиду,
когда вы создаете файл с этим кодом, то время работы скрипта не изменить и не остановить. smile .
Добрый день! Хочу показать как я делаю грабберы на curl

<?php
$url="http://yandex.ru/";//url сайта жертвы
error_reporting(0); //на всякий случай отключаю показ ошибок, но эту строк я вставляю в самую последнюю очередь

$curl = curl_init();//включаем процес
curl_setopt($curl, CURLOPT_URL, $url);//подключаемся к $url
curl_setopt($curl, CURLOPT_REFERER, "http://yandex.ru");//подставляем рефера
curl_setopt($curl, CURLOPT_RETURNTRANSFER,1);
curl_setopt($curl, CURLOPT_TIMEOUT, 30);//ставим тайм аут(необезательно)
$stranica = curl_exec($curl);//присваеваем к переменной
curl_close($curl);//заканчиваем процес
echo $stranica;
?>

Вот собственно и все. Можно еще (точнее нужно) вырезать заголовки, шапки, рекламы, надписи ненужные, поменять юрлы и т.д. Главное что страница у вас на сервере=)
Создаем фоновый вечно работающий php скрипт в Linux (Демон на php).

Демоны - процессы, работающие в фоновом режиме.
Для нужд проекта нужно было написать программу которая будет
в фоновом режиме каждых 30с. проверять нужные параметры и рассылать уведомления пользователям.
Функция проверки запущен ли уже процесс в linux:
<?
/**
* Проверка на повторный запущенный процес в LINUX
* В случае если процесс запущен второй раз функция возвращает TRUE иначе FALSE
* пример: is_running_process('test.php');
* Author: GANJAR
* ICQ: 993770 Site: http://mytu.ru
*
*
* @example is_running_process($process_name);
*
* @param string $process
* @return bool
*/
function is_running_process($process){
    exec( 'ps axw | grep -v grep | grep '.escapeshellarg($process), $output);
    $enabled = false;
    foreach($output as $process_line) {
        if	(preg_match('!\d+\s+(\d|\?)+\s+[S|I|R|N]+\s+!i', $process_line))	{
            if($enabled){
                return TRUE;
            }
            $enabled = true;
        }
    }
    return FALSE;
}
?>
Пример использования:
1. создаем *.php, пишем туда такие строчки:
 #!/www/php/services/php -q
<?php
    set_time_limit(0);
//---------------------------//        Some Function
  /**
  * Проверка на повторный запущенный процес в LINUX
  * В случае если процесс запущен второй раз функция возвращает TRUE иначе FALSE
  * пример: is_running_process('test.php');
  * Author: GANJAR
  * ICQ: 993770 Site: mytu.ru
  *
  *
  * @example is_running_process($process_name);
  *
  * @param string $process
  * @return bool
  */
  function is_running_process($process){
      exec( 'ps axw | grep -v grep | grep '.escapeshellarg($process), $output);
      $enabled = false;
      foreach($output as $process_line) {
          if	(preg_match('!\d+\s+(\d|\?)+\s+[S|I|R|N]+\s+!i', $process_line))	{
              if($enabled){
                  return TRUE;
              }
              $enabled = true;
          }
      }
      return FALSE;
  }
//---------------------------//        Run
    if(!is_running_process(basename(__FILE__))){

        while(TRUE){
                
                //Нужные действия
                echo "Run program from mytu.ru \nsleep 30s - date ".date('Y-m-d H:i')."\n";
                sleep(30);
        }

    } else {
        echo "Error. ".basename(__FILE__)." running\n";
    }

?>
Строка
<?if(!is_running_process(basename(__FILE__)))?>
- не допустит клонирования процесса.
То есть проверит запущен ли уже процесс текущего файла
и в случае если процесс не найден выполнит нужный нам код. Иначе - получим соощение об ошибке.
2. добавляем в крон созданный скрипт с интервалом запуска в 10мин.
В итоге получим одиночный вечноработающий процесс скрипта.
Применения могут быть самые разнообразные: от проверки доступности сайта (uptime) до различных парсеров, кэширования сайта.
Статья не для гуру =)
Писать консольные скрипты приходится не часто, но всё-таки приходится. Не учить же для этого Shell (хотя знание его желательно), тем более, если надо что-то срочно написать и из языков вам известен только PHP. В этой статье я раскажу о написании консольных скриптов на PHP для Linux.
Итак, открываем терминал и создадим для начала какой-то тестовый файл:
$ touch test
Сделаем его исполняемым:
$ chmod +x test
Теперь возьмёмся за его редактирование:
$ nano test
и напишем туда следующее
#!/usr/bin/php
<?php
echo 'Привет, мудак))';
?>
дальше Ctrl+X и сохраняем файл. Первая строка обозначает путь к интерпритатору, дальше идёт PHP-код. Собственно и простенький скрипт готов. Можно запустить
$ ./test 
То что выведет думаю понятно =)
Напишем в содержимое файла следующее
#!/usr/bin/php
<?php
print_r($_SERVER);
?>
и запустим. Выведет что-то наподобии этого

Array
(
[rvm_gemsets_path] => /home/fuelen/.rvm/gemsets
...........
[PATH_TRANSLATED] => ./test
[DOCUMENT_ROOT] =>
[REQUEST_TIME] => 1310847154
[argv] => Array
(
[0] => ./test
)

[argc] => 1
)
Обратите внимание на последние 2 элемента массива: argv и argc. Первый - массив значений, переданных через командрую строку; второй - число значений. Всегда будет как минимум 1 элемент в массиве - это адрес скрипта. Эти переменные также доступны просто как $argc и $argv. Изменим наш скрипт и запишем туда следующее
#!/usr/bin/php
<?php
//распечатываем содержимое массива только тогда
//когда есть доп. параметры
if($argc >1){
    print_r($argv);
}
?>
Запустим скрипт, добавив немного параметров:
$ ./test ololo blblbl
На экране мы увидим следующее

Array
(
[0] => ./test
[1] => ololo
[2] => blblbl
)
Наверное у вас возник вопрос как получить какое-то значение при исполнении скрипта? Очень просто
<?
$a = trim(fgets(STDIN));
Переменной $a будет считана 1 строка из STDIN (подробнее о потоках ввода и вывода смотреть тут).
Ну и на останок простенький скрипт, который будет получать данные в процессе исполнения скрипта:
#!/usr/bin/php
<?php
echo "ваше имя: \n";
$name = trim(fgets(STDIN));
echo "ваша фамилия:\n";
$surname = trim(fgets(STDIN));
echo "кукареку $surname $name!!!\n";
?>
Вот код

<?php
$date = date('d.m.Y / H:i:s', time() + ($sdvigclock*3600));
//узнаем дату и время
$UR = getenv("REQUEST_URI");
//узнаем запрос страницы
$X = getenv("HTTP_X_OPERAMINI_PHONE_UA");
//узнаем модель
$RIP = getenv("REMOTE_ADDR");
//узнаем iр
$R = getenv("HTTP_X_FORWARDED_FOR");
// узнаем локальный iр
$U = getenv("HTTP_USER_AGENT");
//узнаем браузер
$H = getenv("HTTP_REFERER");
//узнаем откуда пришел

$f = fopen("../../data/ref.txt",'a');
//записываем в файл
flock($f,2);
fwrite($f,"<font color=\"green\">Пользователь:</font> $login<br /><font color=\"green\">Дата и время:</font><br/>$date<br /><font color=\"green\">Браузер и модель:</font><br/>$U($X)<br/><font color=\"green\">Адрес IP:</font><br />[$RIP]<br/><font color=\"green\">Адрес IP (Локальный):</font><br />[$R]<br/><font color=\"green\">Адрес URL(откуда):</font><br/><a href=\"$H\">$H</a><br/><font color=\"green\">Адрес URI(запрос):</font><br /><a href=\"$home$UR\">$UR</a>\n");
//записываем все содиржимое(логин не палучиться,надо самому писать.)
fclose($f);//закрываем
?>

открываем файл к примеру stаt.рhр
<?php
echo'Лог посещений';
include('../../data/ref.txt')';
?>
Думаю инфа всем встречалась.:-)
Облако тегов / Авторы