pro-zenit.ru

Виртуальный магазин? Всего 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
Вариант 2 - .htaccess или httpd.conf
Итак, нам надо для 1) и 2) пунктов подправить переменные PHP-процессора: session.save_path (временный каталог) и session.name (присвоить знаначение "SID").


Настройка каталога

  • создать файл shop.txt ПО ТАКОМУ ОБРАЗЦУ. Если вы захотите добавить новые колонки, то не забудьте, что первой кононкой должны идти ID товаров (например числа от 1 до ..), а последней - цена товара. Разделитель товаров - слеш (\).

  • создать файл shop.phtml (имя не принципиально), код программы приведен ниже.


    Текст программы

    
    <?
    
    // символы "<?" должны быть первыми(!) в файле. Т.е. ни пустых строк, ни
    // пробелов до символов "<?" ставить нельзя, иначе не будет работать
    // 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='Внести изменения'> &nbsp; &nbsp;".
            "<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>&nbsp;</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++) {
             // если ячейка пустая, там надо поместить "&nbsp;";
             if (strlen($a[$j])==0) echo "<tD>&nbsp;</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>
    
      <?
    }
    
    
    ?>