Виртуальный магазин? Всего 3 часа работы и 5 Kb кода
Автор: Дмитрий Бородин
Что это?
Это так называемый виртуальный магазин, т.е. прайс лист
некой организации с наименовнием товаров,
часть из которых можно ПОМЕТИТЬ и занести в корзину, чтобы
в дальнейшем можно было заполнить анкету (ФИО, адрес и т.д.) для
покупки этих товаров. Все проще простого. Дизана нет никакого,
только "скелет".
Требования: где ЭТО будет работать?
На win/unix в PHP версии не ниже 4.0 с поддержкой сессий.
Включенных cookies от поcетителей не требуется. Надо лишь правильно
настроить некоторые опции PHP, чтобы программа получила
доступ к сессиям (будет написано ниже).
А почему размер файла 10Кб, а не 5Кб?
Если выкинуть все комментарии, вот и будет 5 кб :-)
Программа (без комментариев) была написана за 3 часа в присутствии
человека, изучающего ПХП. Комментарии, на самом деле были, но только устные :-)
Подготовка сервера
1. Возможный глюк: у вас не настроен временный каталог на сервере
для размещения временных файлов.
2. Программа подразумевает, что PHP поместит в переменную $SID
номер сесии. По умолчанию, возможно, этого не произойдет.
Для решения проблемы 1) и 2) пунктов надо изменить опции PHP.
Это можно сделать в php.ini или файлах httpd.conf/.htaccess.
Вариант 1 - php.ini
Если править php.ini, то в нем уже есть те переменные, что надо изменить
- ищем строку session.save_path и пишем путь к своему временному каталогу. В этот каталог
Apache/PHP будут писать свои файлы, след. для них там должен быть
доступ. Если у вас Unix, то пишем /tmp,
если Windows, то \temp (не забудьте
создать C:\TEMP или X:\TEMP, смотря где находится Апач)
- ищем строку session.name и заменяем на SID (большими буквами)
Вариант 2 - .htaccess или httpd.conf
Если вносить те же измения в указанные файлы, то надо написать так:
- вариант для unix: php_value session.save_path /tmp и для windows: php_value session.save_path \temp
- и имя сессии: php_value session.name SID
Итак, нам надо для 1) и 2) пунктов подправить переменные
PHP-процессора: session.save_path (временный каталог) и session.name
(присвоить знаначение "SID").
Настройка каталога
- создать файл shop.txt по такому образцу (здесь файл *.zip).
Если вы захотите добавить новые колонки, то не забудьте, что
первой кононкой должны идти ID товаров (например числа от 1 до ..),
а последней - цена товара. Разделитель товаров - слеш (\).
- создать файл shop.phtml (имя не принципиально),
код программы приведен ниже.
Текст программы
<?php
// символы "<?" должны быть первыми(!) в файле. Т.е. ни пустых строк, ни
// пробелов до символов "<?" ставить нельзя, иначе не будет работать
// header - появятся warning'и
unset($t);
session_start();
/*
функция прибавляет в корзину новый товар, где $n - это номер строки
в shop.txt. Далее, в сессиях сохраняется не номер строки, а число ID
из shop.txt и используется повсеместно. Если товар уже существует,
то корзина никак не меняется.
*/
function tadd($n) {
global $t;
// открыли файл
$f=file("./shop.txt") or die("файл не найден");
// и получили нужную строку с товаром (в массив $o)
$o=explode("\\",$f[$n]);
$id=$o[0];
if (isset($t[all][$id])) return; // если товар уже в корзине - выход
$t[all][$id]=$id; // флаг, благодаря которому, двумя строчками выше
// мы определили, что товар уже есть в корзине
$t[$id][name]=$o[1]; // наименование
$t[$id][info]=$o[2]; // инфо
$t[$id][cena]=$o[3]; // и д.р. не значащие данные
$t[$id][kol]=1; // кол-во в начале равно "1 штуке"
session_register("t"); // записали переменную в сессию
}
/*
Рисует таблицу с товарами в корзине. Из файла shop.txt мы читаем только
названия колонок и не более. Названия товара (в данном случае только
название/цена/кол-во) берется из сессии.
*/
function korzina() {
global $t,$PHP_SELF,$SID;
$f=file("./shop.txt") or die("файл не найден");
$ogl=explode("\\",$f[0]);
echo "<form action=$PHP_SELF method=POST>".
"<input type=hidden name=SID value='$SID'>". // передаем сесиию
"<input type=hidden name=c value=kolvo>".
// рисуем заголовок таблицы с корзиной:
"<table border=2><tR><td>$ogl[1]</td></td><td>$ogl[3]</td>".
"<td>кол-во</td><td>команды</td></tr>";
// проходим массив $t[all] по списку его ключей
$k=@array_keys($t[all]);
for ($i=0; $i<count($k); $i++) {
$id=$k[$i];
echo "<tr><td>{$t[$id][name]}</td>".
"<td>{$t[$id][cena]}</td>".
"<td><input size=4 type=text name=v[$id] value={$t[$id][kol]}></td>".
"<td><a href=$PHP_SELF?c=del&id=$id&SID=$SID>удалить</a></td></tr>";
}
// внизу таблицы две кнопки:
// Измениения - сохранить изменение числа товаров и обновить страницу
// Заказ - сорх. изм. + перейти на страницу оформления заказа
echo "</table><input type=submit name=edit value='Внести изменения'> ".
"<input type=submit name=zakaz value='Оформить заказ'></form>";
}
/*
Выводит на экран таблицу с товарами. В таблице автоматом генериться новая
колонка с checkbox'асами, отметив которые и нажав "добавив", можно
занести товары в корзину.
*/
function price() {
global $t, $PHP_SELF,$SID;
$f=file("./shop.txt") or die("файл не найден"); // читаем файл
$ogl=explode("\\",$f[0]); // из него берем огравление
$x=count($ogl); // вычисляем число колонок
$y=count($f); // и число строк
// форма (не забываем вписать $SID) + начало таблицы:
echo "<form action=$PHP_SELF method=POST><input type=hidden name=c value=add>".
"<input type=hidden name=SID value='$SID'><table border=2>";
// рисуем заголовок таблицы, названия колонок - первая строка файла shop.txt
echo "<tr>";
for ($j=0; $j<$x; $j++) {
if (strlen($ogl[$j])==0) echo "<tD> </td>";
else echo "<td>$ogl[$j]</td>";
}
// рисуем последнюю колонку, где будут checkbox'ы
echo "<td>x</td></tr>";
// основной цикл вывода прайса
for ($i=1; $i<$y; $i++) {
$a=explode("\\",$f[$i]); // читаем очередную строку файла
if (count($a)<2) continue; // если она пустая (глюки), пропускаем
echo "<tr>";
// цикл вывода всех колонок текущей строки таблицы
for ($j=0; $j<$x; $j++) {
// если ячейка пустая, там надо поместить " ";
if (strlen($a[$j])==0) echo "<tD> </td>";
else echo "<td>$a[$j]</td>";
}
// рисуем тот самый checkbox в последней колонке текущей строки
echo "<td><input type=checkbox name=v[$i] value=$i></td></tr>";
}
echo "</table><br><center><input type=submit value='Добавить ".
"отмеченные товары в корзину'></center></form>";
}
/*
Выводит на экран несколько чисел (написано). Подсчет значений происходит
при каджом вызове.
*/
function summa() {
global $t;
// традиционный проход массива товаров из корзины
$k=@array_keys($t[all]);
for ($i=0; $i<count($k); $i++) {
$id=$k[$i];
// если убрать (double), то копейки округляться
$summ+=(double)$t[$id][kol]*(double)$t[$id][cena];
$summ2+=$t[$id][kol];
}
// просто выводим посчитанные цифры на экран
echo "Корзина: наименований товаров - $i (в кол-ве $summ2 шт),
цена - ".sprintf("%.2f руб.<br>",$summ);
}
/*
Объявление переменной post, которая содержит поля для заполнения
посетителем при оформление заказа. Т.к. этот список используется
2 раза, то описано это именно тут, а не ниже.
*/
$post=array(
"название организации",
"Ф.И.О. должностного лица",
"должность",
"ИНН организации",
"местонахождение организации",
"контактный телефон",
"e-mail");
/*****************************************************************************/
// основной код программы
// $c - основная переменная, указывающая на нужное действие
if (!isset($c)) $c='';
switch($c) {
case "":
// без параметров - рисуем прайс-лист
summa(); // статистика по корзине
price(); // прайс
// ссылка для перехода на корзину
echo "<li><a href='$PHP_SELF?c=korzina&SID=$SID'>Корзина покупок</a>";
break;
case "korzina":
// вывод корзины
summa(); // см. выше
korzina(); // рисуем таблицу корзины
// пишем 2 ссылки
echo "<li><a href='$PHP_SELF?SID=$SID'>Каталог товаров</a>";
echo "<li><a href='$PHP_SELF?c=delete&SID=$SID'>Очистить корзину (осторожно!)</a>";
break;
case "add":
// добавление из формы прайса всех товаров
// в массиве $v скоплены номера строк товаров, которые функция ...
$k=@array_keys($v);
for ($i=0; $i<count($k); $i++) {
// ... tadd() преобразует из файла в данные и поместит в сессии
tadd($v[$k[$i]]);
}
// надо перенаправить браузер на приличный адрес, чтобы:
// 1) в URL был написан приличный адрес
// 2) чтобы не было глюка, если посетитель нажмет ОБНОВИТЬ СТРАНИЦУ
exit(header("Location: $PHP_SELF?c=korzina&SID=$SID"));
// Ну, а то, что header засунуто в exit... Это просто фича такая :-)
break;
case "kolvo":
// измение кол-ва товаров, когда а странице КОРЗИНА нажимают СОХРАНИТЬ
// ИЗМЕНЕНИЯ или ОФОРМИТЬ ЗАКАЗ..
// Оцените, насколько короткий код преобразования корзины
$k=@array_keys($v);
for ($i=0; $i<count($k); $i++) {
$t[$k[$i]][kol]=abs(intval($v[$k[$i]]));
}
// после изменения переенной сессии ее нужно записать
session_register("t");
// Далее важная проверка. Если посетитель нажимает кнопку СОХРАНИТЬ, то
// у нас устанавливается переменная $edit, которая содержит строку
// "Сохранить изменения". Если он нажимает ЗАКАЗ, то устанавливается
// $post. Устанавливается только одна из этих твух переменных.
// если это было ИЗМЕНИТЬ, то переправить на корзину
if (isset($edit)) exit(header("Location: $PHP_SELF?c=korzina&SID=$SID"));
// иначе переправить на страницу с офрмлением заказа
exit(header("Location: $PHP_SELF?c=zakaz&SID=$SID"));
break;
case "del":
// удаление товара по его $id
$id=intval($id);
unset($t[$id]);
unset($t[all][$id]);
session_register("t");
exit(header("Location: $PHP_SELF?c=korzina&SID=$SID"));
break;
case "delete":
// удаление всей корзины.. Как и в пред. пункте, только с проходом
// массива id товаров
$k=@array_keys($t[all]);
for ($i=0; $i<count($k); $i++) {
unset($t[$k[$i]]);
unset($t[all][$k[$i]]);
}
session_register("t");
exit(header("Location: $PHP_SELF?c=korzina&SID=$SID"));
case "zakaz":
// форма для оформления заказа
echo "<form action=$PHP_SELF method=post><input type=hidden name=c value=post>".
"<input type=hidden name=SID value='$SID'>".
"<table border=1>";
for ($i=0; $i<count($post); $i++) {
echo "<tr><td>$post[$i]</td><td><input type=text size=40 name='v[$i]'></td></tr>";
}
echo "</table><input type=submit value='Отправить заказ'></form>";
break;
case "post":
// генерим и отправляем анкету посетителя, где указаны данные посетителя
// и список товаров из корзины
$msg="Анкета посетителя:\n\n";
for ($i=0; $i<count($post); $i++) {
$msg.="$post[$i]: ".substr($v[$i],0,500)."\n";
}
$msg.="\nСписок покупок:\n\n";
$k=@array_keys($t[all]);
for ($i=0; $i<count($k); $i++) {
$id=$k[$i];
$msg.=($i+1).") {$t[$id][name]} \\ ".doubleval($t[$id][cena]).
" руб \\ {$t[$id][kol]} шт. \\ = ".
sprintf("%.2f",$t[$id][cena]*$t[$id][kol])." руб\n";
}
?>
<table width=100% height=95%><tr><td align=center>
<h2>Ваш заказ отправлен!<br>
Спасибо за покупку!</h2>
<hr width=60%><br>
<a href='/?<?=SID?>'>страница сервера</a><br><br>
<a href='<? echo $PHP_SELF; ?>?<?=SID?>'>прайс-лист</a>
</tD></tr></table>
В переменной $msg хранится анкета посетителя,
с которой можно сделать все, что угодно (послать мылом,
записать в лог-файл, вывести на экран):
<pre><? echo $msg; ?></pre>
<?
}
?>