Только для читателей Lifeexample возможно открыть интернет-магазин на Moguta.CMS со скидкой в 15%
Корзина для интернет магазина php
Здравствуйте уважаемые читатели блога LifeExample, сегодня мы продолжим создавать интернет магазин с помощью PHP и реализуем еще несколько его модулей собственными руками. В прошлой части урока мы реализовали такие компоненты как каталог, карточка товара, и ЧПУ, а также сделали задел для системы наполнения каталога. Сегодня мы будем заниматься разработкой маленькой корзины для интернет магазина.
Предыдущие уроки:
Пока я не начал описывать рабочий процесс, хочу выразить благодарность первым комментаторам, задающим толковые вопросы, а также тем людям, которые отсылают свои вопросы на мой контактный адрес. Спасибо, за то, что вы есть, и за то, что помогаете мне своими вопросами найти силы не опускать руки, по данному проекту и продолжать его развитие.
Еще хочу заметить, весь код, который я представляю, не претендует на 100% правильность и в ваших силах найти в нем ошибки и оптимизировать, так как вы считаете нужным. Целью данного проекта является не дать вам готовую «болванку» интернет магазина, а научить всех желающих мыслить и самостоятельно разрабатывать PHP программы. Теперь давайте перейдем к процессу разработки нашей системы.
Предлагаю сразу скачать материалы по данному уроку, для наглядности наших дальнейших действий.
Приступим. Какой же интернет магазин без корзины, в которую можно положить товар? Правильно, таких магазинов не существует, поэтому сейчас мы разработаем скрипт для маленькой корзины.
Маленькая корзина для интернет магазина
Под термином маленькая корзина, я понимаю тот интерфейс представления отложенных для покупки товаров, который, как правило, размещается в шапке сайта.
Маленькая корзина служит своеобразным индикатором для посетителей, по которому пользователь может ориентироваться в количестве отложенных товаров и итоговой сумме заказа.
С первого взгляда, кажется, что нет ничего проще, чем реализовать подобную вещь, с помощью сессии, но существует ряд подводных камней. Например, если поставить задачу: чтобы при возврате пользователя на сайт корзина была наполнена теми же товарами, что и на момент его выхода. В этом случае просто сессией не обойдешься.
Существует несколько способов решения данной задачи:
- Хранить содержимое корзины для каждого зарегистрированного пользователя в БД
- Хранить содержимое корзины любого пользователя в Cookies браузера
В большинстве случаев второй вариант подходит лучше первого, поэтому мы его и разработаем. Т.е. в итоге у нас корзина должна работать в связке session + cookies
Приступим, отрываем header.php и вставляем в верстку вывод нашей корзины:
1 2 3 4 5 | <div class="smalcart"> <strong>Товаров в корзине:</strong><?=$smal_cart['cart_count']?> шт. <br/><strong>На сумму:</strong><?=$smal_cart['cart_price']?> руб. <br/><a href=''>Оформить заказ</a> </div> |
Здесь у нас фигурирует вызов содержимого массива $smal_cart , который будет доступен в шаблоне после дальнейших действий.
Для удобного восприятия добавим в style.css стили для корзины:
1 2 3 4 5 6 7 8 9 10 11 12 | #header .smalcart{ float:right; height:55px; padding: 10px; padding-left: 15px; margin: 10px; border: 1px solid gray; border-radius: 10px; -moz-border-radius: 10px; -webkit-border-radius: 10px; background: #E6DEEA; } |
Можете посмотреть на то, как изменился внешний вид сайта. Теперь давайте углубимся в структуру системы и начнем создавать нужные файлы.
Так как компонент маленькая корзина для интернет магазина не является отдельной страницей, то контроллера для нее мы создавать не будем, внешнее представление у нас уже есть в общем шаблоне, поэтому и отдельного views она тоже иметь не будет, а вот model все-таки придется сделать.
В папке \application\models\ создадим файл cart.php с таким содержанием:
1 2 3 4 5 6 7 8 9 10 11 12 | class Application_Models_Cart { function addToCart($id, $count=1) { $_SESSION['cart'][$id]=$_SESSION['cart'][$id]+$count; return true; } function delFromCart($id, $count=1){} function clearCart(){} } |
Данная модель будет обновлять информацию о содержимом корзины. Пока нам достаточно иметь только функцию добавления товаров, но на будущее создадим интерфейсы для функций удаления товаров и отчистки корзины.
Все данные о продуктах из корзины, у нас будут храниться в массиве $_SESSION в виде ассоциативного массива, ключами которого будут ID продуктов, а значением – количество этих продуктов в корзине. Такой минимализм сыграет нам на руку при передаче этой информации в куки.
Теперь у нас есть модель Application_Models_Cart, и логично предположить, что она должна, откуда-то вызываться. Вызываться модель будет из контролера каталога. Почему каталога? Потому, что ссылки ‘В корзину‘ у нас расположены на странице каталога, завязанной на файлах view-controler-model относящихся к компоненту catalog. А еще и потому, что пока переходить на страницу большой корзины мы не будем. При нажатии на данные ссылки, мы должны оставаться на странице каталога, а информация в маленькой корзине должна изменяться.
Кстати о ссылках, ‘В корзину‘ , давайте сразу изменим значение атрибута href в представлении каталога
1 | <a href="/catalog?in-cart-product-id=<?=$item["id"]?>">В корзину</a> |
В результате получим ссылку вида
1 | http://lifeexampleshop.ru/catalog?in-cart-product-id=1 |
При клике пользователя на данную ссылку, mvc-система передаст управление в application /controllers/catalog.php. Куда мы сейчас вставим нужный код обработчика данного события:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | class Application_Controllers_Catalog extends Lib_BaseController { function index() { if($_REQUEST['in-cart-product-id']) { $cart=new Application_Models_Cart; $cart->addToCart($_REQUEST['in-cart-product-id']); Lib_SmalCart::getInstance()->setCartData(); header('Location: /catalog'); exit; } $model=new Application_Models_Catalog; $Items = $model->getList(); $this->Items=$Items; } } |
Поясню, что тут происходит. Сначала проверяется, был ли щелчок по ссылке и передался ID продукта, который нужно добавить. Если GET параметр in-cart-product-id содержит ID , то управление передается в модель, которая функцией addToCart() , добавляет в корзину нужный продукт, либо только увеличивает его количество. Строка Lib_SmalCart::getInstance()->setCartData() , требует отдельного внимания, поэму я пока ее пропущу, представим, что ее просто нет. На этом этапе у нас есть вся информация о содержимом корзины интернет магазина, и хранится она в сессии. Поэтому мы можем спокойно вернуться на страницу каталога с помощью редиректа:
1 | header('Location: /catalog'); |
Так как мы пока не знаем что такое AJAX и без перезагрузки страницы никак не сможем обойтись, мы просто возвращаемся на страницу каталога, для того чтобы увидеть изменения в корзине. (Об основах AJAX можно прочесть тут.)
На этом можно было бы остановиться, если бы не стояла задача сохранения информации при возвращении пользователя после закрытия браузера. Самое время вернуться к пропущенной строчке:
1 | Lib_SmalCart::getInstance()->setCartData(); |
Стоит предупредить, что далее людям, мало разбирающимся в ООП, будет сложно понять код построчно, но в рамках общего смысла не будет ничего сложного. Что же происходит в этой строке:
- Lib_SmalCart – интерпретируется нашей системой как создание экземпляра класса SmalCart, расположенного в \lib\smalcart.php
- ::— получаем доступ к функциям класса
- Вызов любой функции данного класса должен проходить через функцию getInstance(), в задачи которой входит отсеять все возможные повторные попытки создания экземпляра этого класса. Такой метод называется Singleton.
- setCartData() – сериализует данные о корзине из сессии, и записывает их в cookie.
Для более четкого представления откройте файл \lib\smalcart.php в нем я постарался подробно описать суть каждой функции, поэтому особо комментировать нечего. Единственное, что нужно сказать это то, что вызов метода getCartData() этого класса, происходит и в файле function.php , который является еще одним отделителем логики от верстки и записывает в переменную $smal_cart всю необходимую для вывода информацию.
Помните первым шагом в этой статье мы в header.php вставили код:
1 2 3 4 5 | <div class="smalcart"> <strong>Товаров в корзине:</strong><?=$smal_cart['cart_count']?> шт. <br/><strong>На сумму:</strong><?=$smal_cart['cart_price']?> руб. <br/><a href=''>Оформить заказ</a> </div> |
Так вот, теперь вы наверняка понимаете, откуда берется данный массив $smal_cart и можете заметить, что логическая цепочка обмена информации замкнулась.
Стоит заметить, что при отключенных куках, данный механизм функционировать не будет, ровно также как и любой механизм, использующий сессии, так как идентификатор сессии для ее корректной работы хранится и передается все теми же кукмами.
Всем тем, кому требуются более тщательные объяснения, советую писать вопросы в комментариях, либо мне на e-mail.
Сегодня мы добавили немало кода, который требуется обмозговать и переварить, прежде чем преступать к следующим частям магазина. Надеюсь, что у вас не возникнет трудностей с пониманием данной статьи “Корзина для интернет магазина php”. Если вы еще не подписались на e-mail или rss рассылку, не стесняйтесь — подписывайтесь. Скачать листинг данного урока можно по ссылке:
<<< Предыдущий урок | Следующий урок >>>
Читайте также похожие статьи:
Чтобы не пропустить публикацию следующей статьи подписывайтесь на рассылку по E-mail или RSS ленту блога.
Комментарии
Привет, Марк!
Спасибо большое, я, вроде бы все понял из урока 3.
Один вопрос: я слышал, что для быстродействия лучше использовать динамическую подгрузку классов, чем «require». Что вы по этому поводу думаете?
Да , Алексей, динамическая подгрузка классов лучше чем подключение по «require», у нас она реализована с помощью функции __autoload() из конфигурационного файла. Require‘ ом мы подключаем файлы шаблона и файл функций.
По части проверки включены куки или выключение, конечно в идеале она нужна, но т.к. это всего лишь урок мы без нее обойдемся. А вообще чтобы проверить их активность много труда не составит. Нужно проверить на существование массив $_COOKIE и соответственно обработать ответ.
А, и еще.
Нужна, наверное, проверка активации куки у клиента.
И если куки отключены — то при нажатии на кнопку «добавить в корзину»
появляется сообщение «активируйте сначала кукис!».
2
3
4
5
Warning: mysql_connect() [function.mysql-connect]:... in Z:\home\test1.ru\www\config.php on line 25
Fatal error: Maximum execution time of 30 seconds exceeded in Z:\home\test1.ru\www\config.php on line 25
Евгений эта ошибка у вас проявляется с Листингом №3 ?
Попробуйте скачать 4-й урок, я перезалил архив с исправленными файлами, должно все работать.
Привет
В скрипте, товар с страницы Каталог без проблем добавляется в корзину, а вот со страницы конкретного товара не добавляется в корзину, так задумано или у меня что-то не работает?
Не то чтобы так задумано, я бы сказал — так не додумано. 🙂
В следующей публикации доработаю.
Буду ждать, самостоятельно допилить не получилось.
Привет, Марк. У меня такая проблема
2
3
Warning: Cannot modify header information - headers already sent by (output started at T:\home\proba\www\config.php:1) in T:\home\proba\www\application\controllers\catalog.php on line 12
Ошибка говорит о том что в config.php происходит вывод информации на страницу, что сказывается на работе всей системы. Проверьте config.php, важно чтобы в нем не было никаких выводов echo, print , print_r, var_dump, и тому подобного. Также удалите последний символ ?> если он присутствует, и проследите чтобы в начале файла не было пробелов пере . Кроме того файл должен иметь кодировку utf-8 без BOM .
Спасибо за оперативность. Приятно удивилась. Файл проверила убрала символ ?>, закомментировала вывод echo, пробелов перед знаков препинания не нашла. Результат тот-же. Вот мой файл config.php
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//Error_Reporting(E_ALL & ~E_NOTICE);//не выводить предупреждения
function __autoload ($class_name) //автоматическая загрузка кслассов
{
$path=str_replace("_", "/", strtolower($class_name));//разбивает имя класска получая из него путь
if (file_exists($path.".php")) {
include_once($path.".php");//подключает php файл по полученному пути
}
else{
header("HTTP/1.0 404 Not Found");
//echo "К сожалению такой страницы не существует. [".PATH_SITE.$path.".php ]";
exit;
}
}
//константы для подключения к базе данных
define('PATH_SITE', $_SERVER['DOCUMENT_ROOT']); //сервер
define('HOST', 'zharpizza'); //сервер
define('USER', 'root'); //пользователь
define('PASSWORD', '111111'); //пароль
define('NAME_BD', 'LifeExampleShop'); //база
$connect = mysql_connect(HOST, USER, PASSWORD)or die("Невозможно установить соединение c базой данных".mysql_error( ));
mysql_select_db(NAME_BD, $connect) or die ("Ошибка обращения к базе ".mysql_error());
mysql_query('SET names "utf8"'); //база устанавливаем кодировку данных в базе
В каком редакторе вы работаете?
Посмотрите через notepad++ в какой кодировке файл?
Если он в utf-8 witwout bom, то должно работать. Кстати echo в этом случае можно разкомментировать.
Добрый день! Еще раз спасибо. Я работала в блокноте в UTF-8. Поставила notepad++ переделала кодировку на UTF-8 без bom. Причем сразу несколько файлов, на которые были ссылки в предупреждениях и корзина заработала.
Всё установила, всё работает! Ура. Подскажите пожалуйста,как подключить,(присоединить) другие системы оплаты, такие как PayPal или же Robokassa или билинговые системы оплаты посредством SMS, так как у меня такой контент, который просто нужно скачивать с сайта, и никакой доставки, т.е. — заплатил — и скачивай. СПАСИБО
Дошла до середины не понимаю двух вещей.
1. Где находится папка В папке \application\models\ создадим файл cart.php с таким содержанием:
2. Где находится эта ссылка7
/////Кстати о ссылках, ‘В корзину‘ , давайте сразу изменим значение атрибута href в представлении каталога
1
<a href="/catalog?in-cart-product-id=»>В корзину
В результате получим ссылку вида
1
_http://lifeexampleshop.ru/catalog?in-cart-product-id=1
а что делать если браузер открывает этот файл в виде текста
Надеюсь, это не я оставил последний коммент xDD
ну если все-таки.. то, сам же себе отвечу.. =))
В папке \application\models\ создадим файл cart.php с таким содержанием:
— вот этот код нужно обрамить в теги
вообще с xampp-ом тяжело очень работать, постоянно приходится быть внимательным с путями..
Мне и остальным пользователям xampp
посвящается!
короче, братья!
все траблы с отображением страниц кроются в путях файлов в каталоге application/views как правило.
Обычно бывает достаточно убрать один слэш, чтобы, например путь http://localhost/es/catalog заработал по-человечески, а не радовал 404-й ошибкой object not found (в хроме так пишет)
Настройка виртуального хоста решает проблемы путей.
Единственный толковый гайд, который у меня заработал: (xampp-win32-1.7.7-VC9, windows 7 x64, сборка)
вывод ошибок типа Notice: Undefined offset
решается путем добавления строки
;
в index.php
— остальное работает как по маслу, ы)
хорошо
Так ведь можно всё сделать чрез куки, для чего нужно сочетание сессии+сессии?
Сессии нужны, для того чтобы магазин работал даже у тех, у кого куки отключены.
Не усек, как покупатель подключется к своей корзине потеряв куки, и сессию, для просмотра состояния заказа… может делать по почте и какойнть код на почту , мол проследить можете за заказом..
Здравствуйте, Марк!
Как по Вашему, что означает вот такая ошибка:
Warning: Cannot modify header information — headers already sent by (output started at Z:\home\shop.ru\www\application\controllers\product.php:22) in Z:\home\shop.ru\www\lib\smalcart.php on line 15
Warning: Cannot modify header information — headers already sent by (output started at Z:\home\shop.ru\www\application\controllers\product.php:22) in Z:\home\shop.ru\www\application\controllers\product.php on line 11
Такая ошибка говорит о том, что переl объявлением заголовков происходит вывод данных на страницу, что не есть правильно. Это может случиться от не правильной кодировки файлов. Если вы открывали файлы в обычном блокноте, то он мог сохранить их с битововй маской, т.е. дописать несколько символов перед содержимым файла. Проверьте чтобы все файлы находились в кодировке utf-8 без BOM/
Да! Спасибо за помощь. Протолкнула. Файл Z:\home\shop.ru\www\application\controllers\product.php заканчивался одной лишней пустой строкой, а header нужно отправлять до любого вывода текста в браузер, даже если этот текст- пробелы.
Марк, подскажите пожалуйста сакральное значение параметра ‘p’ в sql-запросе
(файл lib/smalcart.php)
.. всю голову изломал что это и зачем это..
почему p.price? почему product p ?
.. и кстати, для чего $id заключается в фигскобки?
Сакральное значение в следующем: p — это сокращение названия таблицы product, т.е. поля таблицы можно теперь вызывать двумя способами p.price или product.price
фигурные скобки в данном примере , только для более четкого выделения, того что в строку внедрена переменная.
Также используя фигурные скобки можно указать, например, константу.
Доброй ночи, Марк.
пару дней назад писал вам сюда, но так и не дождался ответа, может комментарий не загрузился (здесь я его не вижу), поэтому напишу снова —
делаю магазин обуви. У меня появилась проблема записи товаров в сессию (корзина), я не могу просто записывать товары в корзину как ключ=>значение (id=>count), т.к. есть еще параметр — размер обуви.
Вот смотрите, добавил я, допустим, обувь (Модель-100, артикул = М100) 40-го размера, а следом и 41-го, и как же их записать в массив сессии? Как понимаете простой метод — id=>count здесь не катит, т.к. зависит еще и от размера, ведь я же должен знать, к какому размеру текущей модели относится данный count.
Как решить такой момент?
Мое решение:
Создал таблицу cart (id, article, count, size, sid) sid — это хэш из 10-ти символов, уникальный для каждой сессии.
Здесь я проверяю кроме id и артикул’а еще и размер, если все совпадает — увеличиваю count, иначе — добавляю новую строку.
Данные из этой таблицы конечно удаляются после оформления заказа, и раз в сутки ч/з cron.
Как считаете, нормальное ли решение? Что вы предложите?
Магазин делаю первый раз, поэтому хотел бы знать в начале как правильно, чтобы не ходить кругами.
Если вам удобно, можете написать ответ на почту.
nuklon, да интересное решение с хешем. Должно сработать.
могу ли я разместить корзину на html странице?
Здравствуйте. Большое спасибо за ваши уроки. Столкнулся с такой же проблемой, как и nuklon. Может подскажете, в каком направлении двигаться, если кроме id нужно передать значение из выпадающего списка. Заранее благодарен.
работаю в macromedia dreamweaver. подскажите пожалуйста, у меня не получатся создать корзину вот по этим шагам, когда создаю файл cart.php он у меня не работает, помогите пожалуйста скоро сессия
Как реализовать что бы , было , что товар в наличие столько то или нет ?
Реализовать можно с помощью PHP ))) Добавляйте поле и сохраняйте в него количество.
У меня такая проблема возникла. я могу перейти по ссылке «оформить заказ» в маленькой корзине, только будучи авторизированным под администратора. другой пользователь, либо просто гость не может нажать на кнопку «оформить заказ» в маленькой корзине. в чем может заключаться ошибка?
Здравствуйте, выдает такую ошибку, что делать?
Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in C:\xampp\htdocs\shop\config.php on line 25
getMenu(); ?>
Просто переведите текст, ключевое слово «deprecated»
Скажите… я так понимаю эту корзину можно прикрутить к любому каталогу. Например взять компонент каталога товаров для joomla или доски объявлений и прикрутить к нему эту корзину?
увы, это не так.
Скачал листинг, попробовал запустить — получил ошибку:
К сожалению такой страницы не существует. [C:/OpenServer/domains/cartswfcart.php ]
Я делаю что то не так или же что то не так с самими файлами?
Доброго времени суток! Подскажите, пожалуйста, человеку, далекому от программирования. У нас интернет-магазин мебели. Ранее сайтом занималась фирма, которая, увы, напортачила с корзиной. Ошибка заключается в следующем: «В окошке для изменения количества, изменяя 1 на нужное количество товара и далее при нажатии кнопки «В Корзину», товар уже не добавляется. Если значение 1 не менять, товар добавляется.» Нам никто не может помочь. При просмотре кода страницы нашла кусок, относящийся к корзине. Посмотрите, пожалуйста, где ошибка. Заранее спасибо большое.
<!— —>
В корзину
<!— —>
Здравствуйте!У меня вопрос по синтаксису.Я стараюсь не загружать каждый урок отдельно, а дописывать недостающие команды.В файл application/controllers/catalog он был вида
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//контролер обрабатывает данные каталога
class Application_Controllers_Catalog extends Lib_BaseController
{
function index()
{
$model=new Application_Models_Catalog;
$Items = $model->getList();
$this->Items=$Items;
}
}
/*
Автор: Авдеев Марк.
e-mail: mark-avdeev@mail.ru
blog: lifeexample.ru
*/
?>
я просто добавила строку
2
3
4
5
6
7
8
9
if($_REQUEST['in-cart-product-id'])
{
$cart=new Application_Models_Cart;
$cart->addToCart($_REQUEST['in-cart-product-id']);
Lib_SmalCart::getInstance()->setCartData();
header('Location: /catalog');
exit;
}
система стала выдавать ошибку в последней строке.После того, как убрала закрывающий тег «?>» сайт заработал.Посмотрела Ваш пример, у Вас тоже закрывающий тег отсутствует.Вопрос: почему в данном конкретном случае он должен отсутствовать?