www.romver.ru
/ Раздел Статьи / Проектирование БД, поиск, юзабилити.

Как заказать сайт



  Сегодня я расскажу вам про мой интернет-магазин. Как я решил его сделать и потом переделывал. Как я мучался над архитектурой и организацией логики. Как я рыскал по сети в поисках подходящих юзабилити решений, и что в итоге придумал. Под катом довольно много интересных технических и не очень подробностей.
Чего это я вдругНачну с того, что живу я в славном городе суровых мужиков — в Челябинске. И вот, однажды вечером (около года назад), я подумал, что очень хочу пользоваться интернет-магазином продуктов с доставкой на дом. Просто в холодильнике внезапно всё кончилось, а кодинг шёл в полную силу — с дымом от клавиатуры, и отрываться не хотелось.
А в городе у нас, между тем, нет представительства ни одной фирмы, занимающейся чем-то подобным (типа Ашана или Утконоса). Службы доставки с заказом по телефону не рассматриваю как несерьёзные. Причины такого положения не ясны. То ли они не видят перспектив, то ли далековато до нас, то ли я слишком наивен и у меня всё рухнет и нет никаких шансов, а они уже всё это просчитали и поэтому не лезут =). Короче, кто не рискует — тот не пьёт шампанского. Поэтому будем кодить.

Первый блинОбдумав эту идею, отдал её младшему брату. Сказал выбрать простую бесплатную систему, разобраться, поставить, настроить и запустить. Просто бесплатной системой оказалась OSCommerce. Я как бы и раньше слышал, что сия система не то чтобы очень. Однако ж среди других альтернатив она казалась более-менее доступной, понятной и расширяемой. Боже, как я ошибался…
Короче брат возился с этим !#$^@% несколько месяцев, после чего сайт мы всё-таки запустили. Это было ужасно. Всё скрипело и тормозило, разваливалось и вообще не поддавалось какому бы то ни было расширению и улучшению для удержания посетителей. Короче атас. Поработав в таком виде пару месяцев, было решено снести всё нафиг и начать с нуля.

My first loveВзгляд как-то сразу упал на CakePHP, несмотря на статьи на хабре, восхваляющие Code Ignighter (которого я пока так и не посмотрел).
Мне трудно описать словами тот восторг, который я испытывал создавая по документации что-то типа блога. Это было просто волшебно. Встроенные компоненты, automagic, обработка форм… А возможности связей таблиц — это просто экстаз! Здесь всё уже написано и разрулено до нас — нужно просто сесть и фигачить.
Короче, вы поняли. Отдельно стоит заметить, что в этот раз кодить мы сели вдвоём.

База данныхИтак, магазин продуктов. Опустим, пожалуй, такие тривиальные вещи как пользователи, корзины, категории и т.д. Что действительно интересно — так это организация продуктов.
В OSCommerce всё было просто и понятно. Одна таблица, тупо список.
id#name#price

Таким образом, таблица была заполнена чем-то вроде этого:
Чипсы 90г бекон
Чипсы 120г бекон
Чипсы 90г сыр
Чипсы 120г сыр
Чипсы 240г сыр


Где красота, где рациональность? Надо как-то это улучшить. Самое простое — все вариции засунуть в атрибуты, и придумать механизм их обработки.

Неудачный вариант
таблица products:
id#name#image#base_price

таблица attributes:
id#product_id#attr_type#name#price_change

//price_change предполагалось указывать как изменение цены относительно базовой, например 1.0 или 2.2


attr_type — это тип атрибута, например вес или вкус.

Почему неудачный? Потому что здесь не учтены возможности группировки атрибутов. Например, есть в таблице
вкус: Бекон
вкус: Сыр
вес: 120г
вес: 240г


И как нам указать, что есть товар «Бекон 120г», а «Бекон 240г» нет? Значит нужно указывать правила группировки атрибутов. Развитие этой мысли привело к следующему решению.

Гениальный вариант
mould (англ.) — шаблон, форма для литья.
таблица moulds:
id#name#image
//обратите внимание — здесь нет цены

таблица attributes:
id#attr_type#name
//больше нет product_id и price_change

таблица products:
id#mould_id#price

таблица products_to_attributes
id#product_id#attribute_id


Теперь товар формируется очень гибко. Начём с таблицы attributes. Она заполнена у меня чем-то вроде этого:
1#вес#100г
2#вес#120г
3#вес#150г
4#вес#240г
5#вес#1кг
6#объём#0,33л
7#объём#0,5л
8#объём#1л
9#вкус#бекон
10#вкус#сыр
11#вкус#клубника


Понятно, что attr_type содержит только идентификатор, который указывает на таблицу имён атрибутов — просто здесь вынес для ясности.

Пример записи в moulds
1#Чипсы Lays#lays.jpg

А теперь следите за руками! Who wants to see some magic?
Записи в products
1#1#12
2#1#12
3#1#24


Записи в products_to_attributes
1#1#2
2#1#9
3#2#2
4#2#10
5#3#4
6#3#10


Объясняю. Мы создаём три продукта в соответствующей таблице, указывая mould, который они наследуют, и цену. И тут же назначаем атрибуты. Продукт #1, например, получает вес 120г и вкус бекона, а продукт #3 имеет вес 240г и вкус сыра.
В такой системе можно описать абсолютно любой товар, с любым числом вариаций. Можно даже сделать mould «Cola», и от него создать продукты со вкусами «Mirinda» или «Sprite».

ПоискПоиск занимает особое место в юзабилити моего ресурса (об этом ниже), поэтому к реализации его нужно подойти со всей серьёзностью. В начале я решил поизучать сторонние проекты. Порадовал sphinx, но оказалось что его нужно ставить на машину, а у меня пока только вирт. хостинг. Потом смотрел на Zend Lucene (отдельное спасибо хабраюзеру , который нашёл время выслать мне собственную standalone сборку этой штуки). Смотрел, пробовал, тыкал, ставил, но запустить нормально не смог. Потом также развлекался с fulltext поиском самой mysql, однако тоже безуспешно. Пришлось писать самому.

Тут ничего, как мне кажется, особо гениального нет, но это всё сделано мной лично, а не по чьим-то умным статьям. Поэтому расскажу, пожалуй.
Для организации поиска делаем две таблицы:
searchindex:
id#stem

searchcont:
id#stem_id#modelname#field#model_id#position


Общий принцип работы вполне очевиден. При индексации указываются модели и поля, которые нужно обработать. Затем в цикле выбираются текстовые поля и разбиваются по словам. У каждого слова эвристически извлекаем корень (стемминг), и смотрим — есть ли уже такой же корень в базе. Дописываем в searchcont найденный стем, модель, поле, идентификатор ряда и позицию, на которой находится слово (это нам понадобится для сортировки по релевантности).

При поиске запрошенная строка разбивается на слова, у каждой ищутся совпадения. Затем, если несколько слов найдены в одной записи модели, считаем релевантность. Помните про поле position? Ну так вот, я решил просто посчитать дисперсию набора значений. Грубо говоря, это разлёт значений от среднего. То есть чем кучнее находятся совпавшие слова в записи, тем сама запись релевантнее. Считается по формуле

— это среднее арифметическое всех значений.

Да, согласен, метод довольно грубый. Но у меня поисковая фраза в основном состоит из одного-двух, максимум трёх слов, так что такая оценка вполне приемлема.

ЮзабилитиВ процессе проектирования излазил кучу сайтов — искал советы, варианты, готовые решения. Нашёл много всего полезного и не очень. Многое внедрил, а кое-что только планирую. То, что уже работает (здесь не только классические юзабилити фишки, но ещё и некоторые идеи по организации работы с магазином):
  • Поскольку каталог у меня довольно объёмный (одних только категорий больше 200) было решено сделать упор не на браузинг по каталогу, а на использование формы поиска, которая выделена. Плюс к этому в сайдбаре представлены не все возможные категории, а только популярные.
  • Возможность совершения покупки без регистрации
  • Помощь на месте у каждого пункта
  • Интерфейс с упором на функционал. Из графики только логотип, градиентик на заднем плане и иконки.
  • Связь с оператором прямо из браузера на основе виджета от google talk
  • Аяксовая корзина
  • История покупок с возможностью частично или полностью добавить старый заказ в новую корзину
  • Наличие сущности «пакетов товаров». Грубо говоря, это заранее собранная корзина, имеющая label (название, чтоб не потеряться). Её тоже можно добавить в текущую формируемую либо целиком, либо по частям. Зарегистрированные пользователи могут сами создавать пакеты товаров.
  • Множество тонкостей, недостойных отдельных пунктов: удобная форма регистрации, линки на просмотр корзины и оформление заказа со всех страниц (если пользователь имеет корзину в статусе формирования), все контакты крупно в шапке, кнопка «Купить» у каждого продукта при любом представлении списка товаров (внутри категории, результаты поиска)

То, что планируется:
  • Пользователи, которые купили этот товар, также выбрали...
  • Написать FAQ и инструкцию «Как купить».
  • Есть идея «любимых товаров». Хотя, возможно, это лишнее.
  • Что сейчас на сайте. Кто и что покупает.
  • Надо выдумать какую-то ещё систему взаимодействия пользователей.

В реализации чего я не уверен:
  • Товары представлены «плиткой», по два в ряду. Текущее представление содержимого плитки не очень нравится.
  • Над личной панелью можно (нужно?) работать очень много.
  • ?

Собственно ссылка: ку
Надеюсь, хабрасообществом это не будет вопринято как реклама. Я всего-лишь хвастаюсь своим творением, как разработчик.
Как думаете, может этот магазин стать идеальным? Я имею ввиду как пример реализации интернет-магазина.
habrahabr.ru/blogs/webdev/44338/

Создание сайтов и бесплатный анализ под запросы основных поисковых машин
Контактная информация :
тел. +7(981) 760-8865

e-mail: w e b m a s t e r @ r o m v e r . r u
icq 3681771  © 1997 - 2024 romver.ru