Только для читателей Lifeexample возможно открыть интернет-магазин на Moguta.CMS со скидкой в 15%
Модули интернет магазина
Здравствуй уважаемый читатель блога LifeExample, в этой статье мы продолжим создавать наш интернет магазин своими руками, используя только php и mysql. По плану я хотел начать в этом уроке рассматривать библиотеку JQuery но, кажется до нее еще рановато. В предыдущем уроке посвященном разработке фундамента интернет магазина, я выложил для скачивания готовую MVC систему, на примере которой рассказал о принципах и основах взаимодействия ее составляющих.
Сегодня я уделю большее внимание непосредственно модулям интернет магазина, которые уже реализованы (каталог, меню, форма авторизации). Также мы с тобой уважаемый читатель разберемся с тем, какие еще компоненты и модули необходимы для работы интернет магазина и разработаем механизм преобразования человеко понятных ссылок (ЧПУ).
Если ты читатель в предыдущем уроке не скачал архив, с основой интернет магазина можешь сделать это сейчас:
Любой интернет магазин должен иметь такие составляющие:
- Каталог
- Систему наполнения каталога
- Карточки товаров
- Маленькая корзина
- Большая корзина
- Форма оформления заказа
- Информация о доставке и оплате
Это тот костяк модулей интернет магазина, без которого не осуществится ни одна продажа. В идеале еще должны быть такие компоненты как личный кабинет покупателя, в котором он будет отслеживать состояние своего заказа, система скидок, электронная система оплаты товара и много другое.
Каталог (Модуль представления каталога)
Под каталогом интернет магазина понимают систему представления товаров с возможностью отложить товар для дальнейшей покупки. Другими словами пользователь может ознакомиться с продуктами, которые имеются в наличии и купить те которые ему понравились.
Содержимое каталога хранится в базе данных, где также описаны характеристики всех имеющихся продуктов. В нашей системе уже есть небольшой задел для каталога в виде таблицы product. Так как это лишь учебный каталог пока в таблице находится всего лишь три параметра: название товара, его идентификационный номер и цена.
В реальности таблица может разрастить такими полями как описание, наличие на складе, артикул продукта, особыми ценами, и многими другими параметрами. Кстати к концу этой статьи мы добавим несколько полей в таблицу.
Сейчас таблица имеет такой вид:
Если открыть страницу каталога то мы увидим все содержимое данной таблицы, с картинками соответствующими названиям продуктов.
Картинки хранятся в папке /images , где все они пронумерованы в соответствии с номерами продуктов. Другими словами, если мы создадим новый продукт в таблице, и его номер будет равен 7 , то картинка для этого продукта должна находиться в /images и именоваться как 7.jpg. Такой подход не совсем верный, и имеет ряд плюсов и минусов, правильнее было бы именовать картинки в соответствии с артикулами продуктов. Но так как разрабатываемый интернет магазин всего лишь урок, то для простоты понимания механизма оставим все как есть сейчас. В будущем доработаем этот недочет
На данный момент модуль каталога работает таким образом:
- Система получает запрос на открытие страницы http://lifeexampleshop.ru/catalog
- Соответствующий контролер /application/controllers/catalog.php запрашивает у модели информацию из БД по каталогу.
- Модель /application/models/catalog.php извлекает из БД необходимую информацию и передает в представление.
- Представление показывает нам содержимое каталога в строчку по три продукта.
Система наполнения каталога (Модуль авторизации)
Ни что не вечно под луной. Вот и содержимое витрины в магазинах склонно к частому изменению. С течением времени в любом интернет магазине будут появляться новые товары, заменяя собой старые. И это будет случаться значительно чаще, чем может показаться.
Для того чтобы не лезть каждый раз в mySQL таблицу вручную, мы сделаем специальный модуль интернет магазина реализующий интерфейс для добавления товаров и редактирования уже существующих.
Замечу! Что добавлять товары сможет только пользователь с правами администратора, поэтому нам нужно будет создать отдельную таблицу в базе данных и вносить в нее всех пользователей системы.
Создадим таблицу user и внесем в нее запись администратора.
В идеале пароль должен храниться в md5 хеше, но как видите тут все без премудростей, зато логика работы скриптов как на ладони:
1 2 | Логин: admin Пароль: 1 |
В нашей системе уже действует механизм авторизации, но он примитивен и не использует связь с БД, исправим это. Откроем скрипт модуля авторизации (/application/models/auth.php), и изменим метод ValidData():
1 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 | function ValidData($login,$pass){ $sql = "SELECT * FROM user WHERE login='$login' and pass='$pass'"; $result = mysql_query($sql) or die(mysql_error()); if(mysql_num_rows($result)) { $_SESSION["Auth"]=true; $_SESSION["User"]=$login; } else $_SESSION["Auth"]=false; if (!$_SESSION["Auth"]){ $msg="<em><span style='color:red'>Данные введены не верно!</span></em>"; } else { $msg="<em><span style='color:green'>Вы верно ввели данные!</span></em>"; $unVisibleForm=true; } $result=array("unVisibleForm"=>$unVisibleForm, "userName"=>$login, "msg"=>$msg, "login"=>$login, "pass"=>$pass,); return $result; } |
Коротко о том, что здесь происходит: функция ValidData() получает данные логин и пароль, формирует запрос к БД, в котором пытается найти соответствующую пару, если пара найдена, то авторизация прошла успешно, и в сессию записывается информация о пользователе. Также в переменную $result передается массив значений переменных, который будет доступен контролеру, и тот сможет его корректно обработать и передать необходимую информацию в представление.
Подробная информация о продукте (Модуль карточка товара)
В этом уроке можно было бы обойтись и без карточек товара, но все же для полноты картины создадим еще один важный модуль интернет магазина. Коротко говоря, карточка товара это отдельная страница товара, на которой представлена полная информация и характеристика предлагаемой продукции. С этой страницы, также как и из каталога, пользователь может добавить товар в корзину.
В представленной MVC системе такого функционала еще нет, поэтому сейчас мы его и разработаем.
Создадим три файла product.php и перенесем их в папки views, controllers и models.
Начнем с представления. Файл представления product.php будет иметь следующий вид:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <h1><?=$product['name']?></h1> <div class="card_product"> <div class="product_image"> <image src="/images/<?=$product['id']?>.jpg" /> </div> <div class="product_desc"> <?=$product['desc']?> </div> <div class="price"> <?=$product['price']?> руб. </div> <div class="product_buy"> <a href="/">Купить</a> </div> </div> |
Как и в любом представлении, содержимое этого файла создано лишь для красивого и удобного вывода информции на страницу. Думаю какие либо комментарии тут излишни, пожалуй стоит отметить только то что были добавленны некоторые css стили. В конце статьи можно будет скачать весь листинг данного урока, в котором будут содержаться необходимые css файлы.
Как вы обратили внимание в коде идет работа с массивом $product, для того чтобы его передать в представление с помощью контролера нам нужно сгенерировать этот массив в модели.
Создадим модель product.php, ее код будет выглядеть так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class Application_Models_Product { function getProduct($id) { $sql = "SELECT * FROM product WHERE id='$id'"; $result = mysql_query($sql) or die(mysql_error()); if($row = mysql_fetch_object($result)) { $product=array( "id"=>$row->id, "name"=>$row->name, "desc"=>$row->desc, "price"=>$row->price ); } return $product; } } |
Все что делает эта модель, это получает данные из БД о конкретном продукте по id и передает их контролеру в массиве $product.
Контролер в свою очередь возвращает данные в представление:
1 2 3 4 5 6 7 8 9 | class Application_Controllers_Product extends Lib_BaseController { function index() { $model=new Application_Models_Product; $product = $model->getProduct($_REQUEST['id']); $this->product=$product; } } |
Примечание! С помощью данных из $_REQUEST[‘id’] контролер сообщает модели информацию какого именно продукта нужно вернуть.
Внимание! Еще раз повторю что для работы контролера нужно в GET параметрах передать id запрашиваемого продукта, очень важно запомнить это сечас, так как в дальнейшем нам придется к этому вернуться.
Часть движка отвечающая за вывод подробной информации о продукте , написанна осталось проставить ссылки на страницу карточки товара в представлении каталога:
1 | <a href="/product?id='.$item["id"].'">'.$item["name"].'</a> |
В итоге этих не хитрых манипуляций мы видим результат:
Все бы было хорошо, если бы не одно большое НО! Обратим внимание на ссылки товаров, которые у нас получились:
1 2 3 4 | /product?id=1 /product?id=2 /product?id=3 /product?id=4 |
Вид у них просто отвратительный, с точки зрения SEO оптимизации. Для поисковиков более престижным является вид ссылок такого рода:
1 2 3 4 | /product/kompyuternaya-mysh /product/monitor /product/klaviatura /product/kolonki |
Чтобы нам получить такой красивый вид ссылок, нужно познакомиться с понятием ЧПУ!
ЧПУ – человекопонятные урлы, тоесь ссылки которые можно прочесть и понять смысл их содержимого.
Давайте теперь сделаем так чтобы при переходе по ссылке:
1 | http://lifeexampleshop.ru/product?id=2 |
И при переходе по ссылке:
1 | http://lifeexampleshop.ru/product/monitor |
Мы попадали на одну и туже страницу.
На самом деле это не так сложно как может показаться с первого взгляда, но требуются крепкие базовые знания php. Сначала нам нужно добавить в таблицу product каждому продукту значение, по которому к нему можно будет обратиться из url:
Теперь давайте в классе Lib_Application изменим метод getRoute() который отвечает за маршрутизацию ссылок.
1 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 | private function getRoute() { if (empty($_GET['route'])) { $route = 'index'; } else { $route = $_GET['route']; $rt=explode('/', $route); $route=$rt[(count($rt)-1)]; if($rt[(count($rt)-2)]=="product"){ $sql = "SELECT * FROM product WHERE url like '$route'"; $result = mysql_query($sql) or die(mysql_error()); if($row = mysql_fetch_object($result)) { $_REQUEST['id']=$row->id; $route="product"; } } } return $route; } |
При запуске MVC системы функция getRoute() одна из первых имеет честь быть вызванной. Её задачей является определить название контролера, которому нужно передать управление. Другими словами ссылка любого вида сначала попадает на кухню данной функции, где она обрабатывается и из нее вычисляется название необходимого контролера. Таким образом, мы можем попытаться перейти по абсолютно любой ссылке, а функция в свою очередь должна определить может ли система предложить нам какую-то страницу по запрашиваемой нами ссылке или нет.
Вот в эту функцию мы и вставим обработчик наших человекопонятных (чпу) ссылок. Допустим, мы пытаемся перейти по ссылке:
1 | http://lifeexampleshop.ru/product/monitor |
Это значит, что должен отработать контролер product.php, чтобы выявить этот факт функция проверяет не находится ли в пути ссылке ключевое слово product.
1 | if($rt[(count($rt)-2)]=="product") |
Если все сходится и ссылка содержит раздел product, причем он должен быть предпоследним в пути, то контролер считается определенным и далее система передает управление в /application/controllers/product.php.
Еще одним важным моментом является параметр id, который должен быть передан в контролер. Выше я обращал внимание на то, что контролер получает id из массива $_REQUEST, самое время вспомнить об этом.
Если id не будет передан, контролер не сможет запросить у модели необходимую информацию. Поэтому мы обращаемся к таблице product в нашей БД и находим соответствующий id.
В нашем случае [url = monitor], а [id = 2]. Это значит, что нам надо записать этот номер в массив $_REQUEST:
1 | $_REQUEST['id']=$row->id; |
После этих действий ссылка вида:
1 | http://lifeexampleshop.ru/product/monitor |
системой будет пониматься точно также как и ссылка:
1 | http://lifeexampleshop.ru/product?id=2 |
И результаты вывода будут идентичны.
На этом этапе я предлагаю закончить рассматривать модули интернет магазина, и систематизировать проделанные действия у себя в голове. Оставшиеся не затронутыми в этой статье компоненты я обязательно опишу в следующей публикации. Оставляйте свои положительные и отрицательные комментарии, все они будут учтены в следующей статье.
<<< Предыдущий урок | Следующий урок >>>
Читайте также похожие статьи:
Чтобы не пропустить публикацию следующей статьи подписывайтесь на рассылку по E-mail или RSS ленту блога.
Комментарии
Хорошая статья, спасибо. Жду продолжения.
Отличная статья, полезно про реализацию ЧПУ.
Согласен!
Думал в этой статье найду ответ… Что такое $member[‘init’]=0 в index.php???
$member[‘init’]=0 — аналог строчке:
Можешь попробовать подставить её, так думаю будет более прозрачно ;- )
Кстати, таким же образом можно заменить /enter?out=1 при выходе из личного кабинета что то вроде /enter/out добавив в Lib_Application:
2
3
4
$_REQUEST['out']=1;
$route="enter";
}
и в view/enter.php заменить ссылку на /enter/out
Как то так…
Относительно /enter/out , да можно сделать так почему бы и нет. Радует, что начали поступать предложения по улучшению кода, ибо это говорит о том, что кто-то все таки его пытается понять. Наверное стоит сказать что в данном коде не паханное поле для его оптимизации. От части это сделано умышлено, для того чтобы вы сами напрягали мозги а не просто запускали на исполнение всю систему и наблюдали за подтверждением теории.
Возникли проблемы при реализации ЧПУ.
Код срабатывает, но отваливается .сss файл!
не срабатывает RewriteCond %{REQUEST_FILENAME} !-f в чем может быть проблема?
п.с. делал все как в примере… вроде бы)))
Прописал полный путь для .css файла, все работает. Но все ровно не могу понять в чем была проблема..
Тоже столкнулся с етой ошыбкой и не понимаю так где прописовать полное имя css файла?
почему при попытке перейти по ссылке каталог или вход, перекидывает на служебную страницу денвера.
Сергей, я думаю, дело в «хитрой» структуре папок в Denwerе…
Если Ваша папка расположена, как рекомендуют создатели, в директории Z:\home\localhost\www\, то в этом случае в путь к сайту примешивается \localhost\… И система ищет эту папку в названиях контроллера для исполнения.
В таком случае рекомендую Вам перенести проект следующем образом…
Z:\home\имя_вашего_проекта\www\ и в этой директории уже размещать Ваш проект
ИМХО, для полноты картины надо маленькое замечание сделать
относительно вот этой записи:
В таблице БД поле url надо сделать уникальным (unique), а то на 2-3 разных товара в этой поле одно значение пропишут и что будет тогда? Мне думается надо бы поправить мальца)
В данном случае при одинаковых URL будет выведен товар занесенный в БД последним.
Все в ваших силах, если считаете нужным правьте. 😉
Mark, Здравствуй!
У меня следующая проблема при добавлении базы в phpmyadmin
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
SQL query:
--
-- База данных: `LifeExampleShop`
--
-- --------------------------------------------------------
--
-- Структура таблицы `order`
--
CREATE TABLE IF NOT EXISTS `order` (
`id` INT( 11 ) NOT NULL AUTO_INCREMENT ,
`date` INT( 11 ) NOT NULL ,
`name` VARCHAR( 255 ) NOT NULL ,
`email` VARCHAR( 255 ) NOT NULL ,
`phone` VARCHAR( 255 ) NOT NULL ,
`adres` VARCHAR( 255 ) NOT NULL ,
`summ` VARCHAR( 255 ) NOT NULL ,
`order_content` VARCHAR( 255 ) NOT NULL ,
PRIMARY KEY ( `id` )
) ENGINE = MYISAM DEFAULT CHARSET = utf8 AUTO_INCREMENT =80;
MySQL said:
#1046 - No database selected
И еще можно ли одним архивом скачать данный пакет уроков, просто база данных из первого нормально добавляется а из остальных выдает ошибку.
Ошибка говорит о том что вы не выбрали базу в которую хотите импортировать таблицы. Я подробно описал алгоритм добавления в комментариях к уроку номер пять. Смотрите в конце комментариев, также там есть скриншот.
Добрый день. Подскажите по функционалу:
Нужно сделать переключатель в описании товара, или поле которое содержит число ( это не сложно, нашел).
А затем цену в корзину считать как — умножить ‘price’ на число введенное в поле. Где это сделать? В каком файле?
Если вы добавили поле с числом в таблицу.
То вам нужно немного изменить модели product.php и cart.php
Нет, я наверное не совсем правильно объяснил. Грубо говоря, мне при нажатии на кнопку «Купить» нужно умножать цену на число которое ввел пользователь.
Подскажите, где происходит обработка события «Купить»
Александр, в любом случае весь расчет стоимости происходит в модели cart.php. А для того, чтобы передать необходимое число, нужно использовать форму, и соответствующий для нее обработчик. Эта задача требует определенных знаний, и вам следует обратиться к профессионалам. Или ко мне через форму обратной связи, для уточнения ТЗ.
А как переделать сам катало в виде дерева раскрывающим tree не как не идёт
У меня проблема, пользуюсь AppServ, при переходе по ссылкам , перекидывает на служебную страницу. И еще отваливается css при реализации ЧПУ
А в контролере не нужно session_start() ? А то у меня не работает авторизация.
Разве в контролере не нужно session_start() ? А то у меня не работает авторизация.
Здравствуйте!
Скажите, пожалуйста, как вы сделали так, что в ссылках нет расширения .php? (product?id=4)
С помощью .htaccess и маршрутизатора.
Добрый вечер, Марк! Можете подсказать, как сделать чтобы выходя из карточки товара через кнопку «назад» попадать не в общий каталог, а в раздел данного товара? Буду очень благодарен за помощь, т.к. мой мозг юного программиста уже дымится)))
«С помощью .htaccess и маршрутизатора.».. а можно пример? Уж больно хочется научиться такое же делать.
Олег, пример листинге урока.
Как создать таблицу user и внести в неё запись администратора?
Не понимаю вашего вопроса. Также как и любую другую таблицу.
вот я чайник php код совсем не понимаю,но так чувствую что он мне родной
Здравуствуйте. А можно сделать что бы модель Application_Models_Product совместить с Application_Models_Catalog что бы не создавать отдельные файлы?
Здравствуйте, можно. 🙂
Здравствуйте Mark!
Подскажите пожалуйста зачем мы наследуем контроллер Lib_BaseController? что конкретно он делает? я что то не до понимаю.
Спасибо заранее.
Дает возможность задавать набор переменных, которые потом будут доступны в представлении.
Подскажите пожалуйста.
Здравствуйте. Разбираю Ваши уроки. Не понял в контроллере каталога
class Application_Controllers_Catalog extends Lib_BaseController
{
function index()
{
$model=new Application_Models_Catalog;
$Items = $model->getList();
$this->Items=$Items;
}
}
В переменную $Items мы получили список товаров. Что
делает строчка $this->Items=$Items; Мы же не создавали в классе переменную $Items. Или переменная приравнивается к самой себе? Можно ли return $Items; вместо этого?
А как реализовать в роутере принцип вложеных категорий. можно просто на словах . что как разбиваем ..
еще важно чтоб в каталоге ссылки были сразу ЧПУ, я изменил в ссылке id на url
я заменил заменил код работы с базой на PDO у меня в массив урл сразу попадает, вам нужно в модельном файле каталога добавить урл в массив
2
3
4
5
6
"id"=>$row['id'],
"name"=>$row['name'],
"price"=>$row['price'],
"url"=>$row['url']
);
‘.$item[«name»].’
Подскажите пожалуйста куда вставить этот код, что я не могу понять!? Заранее спасибо!!!
При открытии какого либо товара пишет «No database selected» на месте информации о товаре
Что может быть?
Столкнулся с тем что если набираю product/monitor стили пропадают
а как открыть базу данных, если пишет неверный пользователь?