http://sulfurzona.ru/
News
Service
Magazine
Software (Battle City Game, Wallpaper manager, Superpad, VG-NOW, Puzzle Game, Netler Internet Browser, ..)
Wing-Thunder Game (fly simulator)
Dune Game (Dune III, Dune IV, Cheats, Forum, ..)
Games free
Turbo Pascal (Assembler, Docs, Sources, Debbugers, ..)
Books (Docs for developers)
Guest book
Компьютерная диагностика двигателя автомобиля (адаптер К-линии)Компьютерная диагностика двигателя автомобиля (адаптер К-линии)
 
 
Скачать игру Крыло-Гром (Wing-Thunder) бесплатно
 
 

PHP и WEB для новичков (часть 13):

 
Автор: Владислав Демьянишин
 

Сортировка и группирование результатов. Куки и сессии

 
PHP и WEB для новичков
В большинстве случаев нам необходимо не только выбирать из базы данные, удовлетворяющие некоторому условию, но и располагать их в определенном порядке. Для этого существует ключевое слово ORDER. Рассмотрим один из последних запросов предыдущей главы:
 
SELECT mp3.title AS song, performer.name AS performer, album.title AS album
FROM mp3, performer, album
WHERE mp3.album_id=album.id AND mp3.perf_id=performer.id
 
выдаст результат (рис. 1):
 
Рис. 1
 
Допустим нам необходимо отсортировать этот результат, скажем, по первому столбцу song. Запрос будет таким:
 
SELECT mp3.title AS song, performer.name AS performer, album.title AS album
FROM mp3, performer, album
WHERE mp3.album_id=album.id AND mp3.perf_id=performer.id
ORDER BY song
 
Результат получим такой (рис. 2):
 
Рис. 2
 
По умолчанию сортировка осуществляется в порядке нарастания или по алфавиту. Если нужно сортировать в обратном порядке, то после названия поля ставится служебное слово DESC. Рассмотрим сортировку в порядке убывания по столбцу album:
 
SELECT mp3.title AS song, performer.name AS performer, album.title AS album
FROM mp3, performer, album
WHERE mp3.album_id=album.id AND mp3.perf_id=performer.id
ORDER BY album DESC
 
Результат (рис. 3):
 
Рис. 3
 
Разумеется, сортировка допускается и по нескольким столбцам сразу. Например, отсортируем результат сначала по столбцу performer по возрастанию, а затем по столбцу song - в обратном порядке:
 
SELECT mp3.title AS song, performer.name AS performer, album.title AS album
FROM mp3, performer, album
WHERE mp3.album_id=album.id AND mp3.perf_id=performer.id
ORDER BY performer, song DESC
 
Результат (рис. 4):
 
Рис. 4
 
Сортировка допускается не только по столбцам результата, но и по другим полям таблицы. Так отсортируем результат по дате выхода песни (это поле не видно в результате, но строки будут упорядочены именно так):
 
SELECT mp3.title AS song, performer.name AS performer, album.title AS album
FROM mp3, performer, album
WHERE mp3.album_id=album.id AND mp3.perf_id=performer.id
ORDER BY mp3.year
 
Результат (рис. 5):
 
Рис. 5
 
Замечу, что сортировка строк тоже зависит от индекса. Так, если мы сортируем результат по полю song, то нам будет необходим индекс на таблицу mp3 по полю title.
 
В данном случае, разумеется (ведь всего три записи в таблице), индекс не нужен. Однако, если количество записей будет исчисляться сотнями и тысячами, без индекса такие записи будут серьезно тормозить.
 
Результат можно тоже ограничить количеством строк. Действительно, если у нас в архиве будет несколько тысяч файлов, то не имеет смысла просматривать их все. Для ограничения количества строк применяется ключевое слово LIMIT.
 
Допустим, что необходимо увидеть лишь 2 строки с предыдущего результата. Запрос будет таким:
 
SELECT mp3.title AS song, performer.name AS performer, album.title AS album
FROM mp3, performer, album
WHERE mp3.album_id=album.id AND mp3.perf_id=performer.id
ORDER BY mp3.year
LIMIT 2
 
Результат (рис. 6):
 
Рис. 6
 
Иногда необходимо просмотреть строки результата не с самой первой строки, а несколько дальше. Что-то вроде просмотра результата по страницам с определенным количеством видимых строк.
 
Так, если выводим строки по страницам, и необходимо вывести строки, скажем, с 10-й по 20-ю, то в этом случае к слову LIMIT добавляется еще один параметр:
 
SELECT mp3.title AS song, performer.name AS performer, album.title AS album
FROM mp3, performer, album
WHERE mp3.album_id=album.id AND mp3.perf_id=performer.id
ORDER BY mp3.year
LIMIT 2, 3
 
Этот запрос выведет одну строку, пропустив две первых (рис. 7):
 
Рис. 7
 
До сих пор мы рассматривали выборку из таблицы по строкам, т.е. каждая строка результата относилась к какой-то записи таблицы. Однако не редко возникает необходимость получить какую-то суммарную информацию по строкам, например, сумму значений некоторого поля.
 
Или минимальное, максимальное или среднее значение поля. Или количество строк, удовлетворяющих условию запроса. Такие операции называются группированием. Для этого предназначены функции SQL, имеющие название агрегатных (aggregate).
Наиболее простая агрегатная функция - это count(). Она возвращает количество строк. В обращении она проста:
 
SELECT count(*) FROM mp3
 
Попробуйте самостоятельно выполнить этот запрос, и вы убедитесь, что результатом будет количество записей в таблице mp3. Конечно, к этому запросу можно добавлять условия. Например, чтобы подсчитать количество записей в mp3 для песен, которые датированы ранее 2007, пишем:
 
SELECT count(*) FROM mp3 WHERE year<2007
 
Следующая агрегатная функция - это sum(). Она возвращает сумму значений поля. Например, чтобы подсчитать сумму размеров файлов в таблице mp3, пишем:
 
SELECT sum(filesize) FROM mp3
 
Конечно, к такому запросу можно добавить условие WHERE.
Аналогичным образом пользуемся функциями min() - минимальное значение поля, max() - максимальное значение, avg() - среднее значение. Допускается использование сразу нескольких функций в запросах и по разным полям, например:
 
SELECT count(*), sum(filesize), min(year), max(year), avg(filesize)
FROM mp3
 
Получим такой результат (рис. 8):
 
Рис. 8
 
Группировать строки можно как по всей таблице, что мы и проделали, так и по некоторому полю. Для этого существует ключевое слово GROUP. Например, надо выбрать сумму размеров файлов для песен по каждому исполнителю.
 
Сначала я покажу запрос, который выбирает песню с названием исполнителя и размером. Как построить такой запрос, должно быть уже понятно:
 
SELECT mp3.title AS song, mp3.filesize AS filesize,
performer.name AS performer
FROM mp3, performer
WHERE mp3.perf_id=performer.id
 
Получим (рис. 9):
 
Рис. 9
 
Теперь нам следует сгруппировать эти песни по имени исполнителя (performer). Разумеется, что название песни тут не будет иметь значения, поскольку в группе их будет несколько, а размер файла будем суммировать:
 
SELECT count(*) AS song_count,
sum(mp3.filesize) AS summary_size,
performer.name AS performer
FROM mp3, performer
WHERE mp3.perf_id=performer.id
GROUP BY performer
 
И результат будет таким (рис. 10):
 
Рис. 10
 
Так, первый столбец показывает количество строк в группе (т.е. количество песен, принадлежащих одному конкретному исполнителю), другой - суммарный размер файлов в группе, а третий - название исполнителя, по которому формируется группа.
 
Разумеется, результат таких запросов можно сортировать при помощи ORDER BY и ограничивать через LIMIT. следует лишь запомнить порядок указания этих слов, поскольку он обязателен. Сначала GROUP BY, за ним - ORDER BY, и только потом - LIMIT.
 

Куки и сессии

 
Чтобы сайт был интерактивным, необходимо, чтобы он мог "запоминать" посетителя.
До сих пор мы рассматривали скрипты, которые выглядят одинаково, независимо от того, что за посетитель их просматривает. Однако, в большинстве случаев это неприемлемо. Как пример, можно привести многочисленные интерактивные сайты, которые "помнят" посетителя - чаты, форумы, блоги.
 
Большинство сайтов тоже имеют что-то наподобие этого - практически каждый, более-менее сложный, сайт имеет систему администрирования, в которую необходимо входить, введя логин и пароль.
 
Одним из способов "запомнить" посетителя являются куки (cookies). На самом деле куки предназначены для хранения некоторой информации в браузере пользователя.
 
Стандарт, определяющий правила пользования кукисами, накладывает ограничения на их размер, поэтому много информации хранить в них не удастся.
Тем не менее, можно хранить некоторую ключевую информацию (например, логин и пароль пользователя), а всю остальную информацию хранить в другом месте (в файле или БД).
 
Куки имеют ограниченный срок жизни - при создании куки следует указать, какое время куки должны храниться в браузере. В качестве примера рассмотрим уже знакомый нам скрипт, отсчитывающий посетителей сайта.
 
Но этот скрипт будет также считать посещаемость каждого пользователя. Обратите внимание на то, что для работы скрипта необходимо в браузере разрешить работу с куки. Тогда новый скрипт counter_test2.php будет таким:
 
<?
// личную посещаемость берем
// из куки и увеличиваем на единицу
$count = $_COOKIE["count"];
 
if(!$count) $count = 0;
$count++;
 
setcookie("count", $count, time() + 86400);
?>
<html>
<head>
<title>тест счетчика</title>
</head>
<body>
<? include_once "count2er.inc.php"; ?>
</body>
</html>
 
Все куки пользователя именно данного сайта доступны из глобального ассоциативного массива $_COOKIE. Обратите внимание на замечание "именно данного сайта".
 
Куки устанавливаются именно для одного сайта, и могут быть прочитаны только скриптами этого сайта. После прочтения куки мы наращиваем их численное значение на единицу и записываем в куки снова функцией setcookie.
 
Первый ее параметр - название куки, второй - значение, третий - срок жизни в секундах. В нашем случае time() + 86400, где 86400=24 часа x 3600 секунд, т.е сутки.
Обратите внимание, что операции над куки выполняются в самом начале скрипта. Это не случайность. Стандарт требует, чтобы установка куки происходила до того, как в страничку будет выведен первый символ (сюда подпадают как вызовы echo, так и простой вывод HTML). Если это требование не соблюдать, мы получим сообщение об ошибке:
 
Warning: Cannot modify header information - headers already sent by
(output started at z:homemultimediawwwcounter_test2.php:1)
in z:homemultimediawwwcounter_test2.php on line 9
 
Такое предупреждение возникает даже тогда, когда нет явного вывода - например, перед первым "<?" в скрипте стоит пробел или перевод строки. Куки в таком случае не установятся. Ну и сам counter2.inc.php:
 
<?
echo "эту страницу просмотрели ";
if(file_exists("counter.txt")) $f = fopen("counter.txt", "r+");
else $f = fopen("counter.txt", "w+");
flock($f, LOCK_EX);
 
$count = fgets($f);
if(!$count) $count = 0;
$count++;
fseek($f, 0, SEEK_SET);
 
fwrite($f, $count);
flock($f, LOCK_UN);
fclose($f);
 
echo $count;
 
$c = substr($count,strlen($count)-1,1);
if( $c > "1" && $c < "5" ) echo " раза";
else echo " раз";
 
$count = $_COOKIE['count'];
 
echo "<br />лично вы просмотрели эту страницу $count";
 
$c = substr($count,strlen($count)-1,1);
if( $c > "1" && $c < "5" ) echo " раза";
else echo " раз";
?>
 
Работа с куками имеет несколько недостатков. Во-первых, в них нельзя хранить много информации. Если информации слишком много, то программист должен позаботиться о том, где ее хранить.
 
Во-вторых, не всегда следует рассчитывать на то, что в браузере посетителя разрешены куки. В-третьих, куки не являются безопасным хранилищем для секретной информации, например, паролей.
 
По соображениям безопасности как раз пароли в них хранить и не следует, поскольку элементарный, специально написанный злоумышленником, небольшой код на JavaScript может помочь ему узнать эту ценную информацию.
 
Да и вообще работу с кукисами при помощи функции setcookie() сложно назвать удобной, учитывая ограничения на вывод в страничку до вызова setcookie().
Этих недостатков нет в другом методе запоминания данных пользователя - так называемые сессии. Сессия - это глобальный ассоциативный массив $_SESSION, в который можно добавлять свои элементы, и они будут видны во всех скриптах для текущего посетителя сайта. Например:
 
<?
session_start();
 
if (!isset($_SESSION['count']))
$_SESSION['count'] = 0;
else $_SESSION['count']++;
 
$count = $_SESSION['count'];
 
echo "вы просмотрели эту страницу $count";
 
$c = substr($count,strlen($count)-1,1);
if( $c > "1" && $c < "5" ) echo " раза";
else echo " раз";
?>
 
Работа с сессией начинается с вызова session_start(). При этом PHP смотрит, не была ли уже начата сессия для данного посетителя. Если да, то все значения переменных сессии загружаются в массив $_SESSION и становятся доступны из скрипта.
 
Если элементу массива $_SESSION['count'] значение еще не было присвоено, то функция isset() вернет false и мы запишем в этот элемент нуль. Иначе увеличим этот элемент на единицу. В любом случае значение этого элемента будет сохранено после завершения скрипта и будет доступно при следующем его выполнении.
В результате мы видим, что в этом примере есть некоторая глобальная переменная $_SESSION['count'], которая увеличивается на единицу при каждом обновлении странички со скриптом. При этом переменная для каждого посетителя своя.
 
На самом деле сессии тоже базируются на куки - при первом посещении странички в браузере сохраняется куки PHPSESSID, по которой PHP идентифицирует ("узнает") посетителя.
 
Однако, во-первых это прозрачно для программиста, поскольку ему не придется заботиться о том, где и как хранить эти данные, а во-вторых, это работает и с выключенными кукисами - в таком случае PHPSESSID передается через строку URL. В любом случае программист не заботится о реализации хранения данных в сессии, он просто с ней работает.
 
В сессии можно хранить достаточно объемные данные, в том числе и созданные объекты. Правда, тут имеются нюансы, но мы их рассмотрим позднее.
 
Продолжение следует…
 
© Владислав Демьянишин
 
 
На нашем сайте можно не только бесплатно скачать игры, но и документацию и книги по программированию на MIDLetPascal, Turbo Pascal 6, Turbo Pascal 7, Borland Pascal, по программированию устройств Sound Blaster, Adlib, VESA BIOS, справочник Norton Guide и много другой полезной информации для программистов, включая примеры решения реальных задач по созданию резидентных программ.
 

Журнал > Программирование > PHP и WEB для новичков (HTML, JavaScript, PHP, MySQL) > PHP и WEB для новичков (часть 13): Сортировка и группирование результатов. Куки и сессии
 
 
 
 
 
 
На главную страницу На предыдущую страницу На начало страницы