Подальшій опис не слід розцінювати як рекламу VirtueMart (далі VM). Мені не доводилося займатися торгівлею, тому довелося витратити деякий час на дослідження готових рішень для інтернет-магазинів. З безкоштовних продуктів сподобалися OpenCart і VM. Остаточний вибір припав на другий варіант з кількох причин, одна з яких простота супроводу, бо мій сайт працює на Joomla! По-можливості, уважно розгляньте код цього додатка. Встановіть PHP 7 на свій локальний сервер і оцінить працездатність VM. Можливо, матеріал даної статті також допоможе вам прийняти остаточне рішення про те, який програмний продукт використовувати в своєму інтернет-магазині.
Установка VM вкрай проста, тому я пропускаю цей крок. Додам тільки, що сайт багатомовний, тому необхідно завантажити і встановити файли підтримки відповідних мов. Далі описується робота з версією VM 3.0.14.
ПРИМІТКА: після установки всіх мов визначте мову за замовчуванням в діалозі Joomla! 'Extensions → Languages', наприклад, English. Справа в тому, що кореневою мовою в VM є англійська, і тому що не всі пакети інтернаціоналізації повністю переведені, то в разі відсутності якоїсь трансляції, можна дозволити повідомлення англійською мовою. Взагалі-то підтримка багатомовності в VM має нюанси в деяких випадках, але про це пізніше.
Починаємо з діалогу Конфігурація (VirtueMart → Configuration), де обов'язково дозволимо встановлені мови:
На наступному кроці описуємо Магазин (VirtueMart → Shop). Діалог простий, але слід все ж зазначити, що розмір картинки логотипу вашої компанії, який буде відображатися на інвойсах, повинен бути в межах 200х38 пікселів і бажано в форматі 'GIF', хоча оголошені підтримуваними і інші формати. Формати інших зображень також бажано стандартизувати для свого сайту. Наприклад, для фотографій виробів я буду використовувати розмір 200 х 149, 96 точок на дюйм.
Після цього визначаємося з валютами, допустимими для магазину, і перш за все створюємо заміщення їх назв в діалозі 'Extensions → Languages → Overrides' як для адміністративної панелі, так і для сайту. Тепер необхідно відкрити 'VirtueMart → Currencies', знайти необхідну валюту і зробити наведене нижче:
Слід мати на увазі, що для основної валюти магазину, яка буде використовуватися при вказівці цін на товари, поле 'Exchange Rate' повинно мати значення 0. У той же час, це поле обов'язково має бути заповнено для інших використовуваних валют:
ПРИМІТКА: основна валюта повинна залишатися незмінною протягом існування магазину. Невикористані валюти можна заборонити для публікації або видалити:
Тепер додаємо ці валюти в діалозі 'VirtueMart → Shop':
Як видно з малюнка заміщення відбулося, але при зміні мови залишається незмінним (див. Список вгорі ліворуч). В панелі адміністратора це терпимо. Але на стороні сайту підстановки взагалі не відбувається:
Виходячи з того, що це ймовірно буде надалі виправлено, я вирішив обійти проблему простою заміною словесного опису валюти на її 3-х символьний код в діалозі 'VirtueMart → Currencies'. Також можна видалити непотрібні тепер заміщення 'VM_CURRENCY ...', які були внесені в 'Extensions → Languages → Overrides'. При цьому, я видалив кнопку 'Change currency'. Для цього створив заміщення модуля 'mod_virtuemart_currencies' і вніс в код його файлу 'default.php' зміни, представлені на наступному малюнку:
Колірна легенда:
Жовтий: код закоментований
Синій: змінено назву
Червоний: доданий код
ПРИМІТКА: докладніше про методику створення заміщень в статті 'Пидтрімка мікророзмітки 'Стаття' в Joomla! 3.x '
Тепер модуль 'VM-Currencies Selector' виглядає на сайті так:
Далі визначаємо Виробників і Категорії, до яких вони належать. У моєму випадку виробник всього один:
Тепер нам потрібно створити кореневу категорію товарів 'Electronics' і вкласти в неї 'Door Bells'. Для цього відкриваємо діалог 'Product Categories' і послідовно описуємо їх для кожної мови, що підтримується сайтом.
ПРИМІТКА: список мов з'являється після першого збереження кожної категорії, що відображено на наступному скріншоті. Надалі, кнопку 'Save' необхідно натискати для збереження опису категорії на кожній мові.
В результаті отримуємо таку структуру:
Створимо опис якого-небудь продукту в категорію 'Door Bells'. Наприклад, кнопки дзвінка:
Тепер можна створити пункт Магазин в Головному Меню Joomla! На своєму сайті я зазвичай розміщую модулі додаткових меню в правій частині екрана. У разі магазину тут буде розташовувано список категорій товарів.
ПРИМІТКА: на даний момент VM підтримує 2 рівня вкладень в модулі списку категорій.
Щоб надалі не опинитися в скрутному становищі, якщо раптом знадобиться додати рівень вкладення, створимо спливаюче меню для пункту виклику діалогу магазину. Для цього треба вказати тип пункту меню 'External URL' і в полі 'Link' внести символ '#', щоб при повторному натисканні на кнопку не відбувалося перезавантаження картинки:
Додамо підлеглий пункт 'Electronics' і вкажемо для нього тип 'VM Category Layout'. Повторимо процедуру для всіх мов і в підсумку отримаємо наступну структуру:
Таким чином, у нас з'явилася можливість при необхідності легко додавати додаткові рівні в меню магазину, і не хвилюватися про вищезгаданому обмеження в модулі списку категорій.
І нарешті, створимо для кожної мови модуль типу 'VM Category', де виберемо категорію 'Electronics' як батьківську:
Перевіримо результат нашої праці:
Загалом заготівля є і на цьому можна було б закінчити цю тему, щоб скоріше зайнятися розробкою і виготовленням самого виробу. Але ж нас цікавить не тільки продаж, але навіть більшою мірою виробництво. А так як перше і друге є похідною від зацікавленості і ступеня задоволення нами інтересів споживача, то важливо закласти міцний фундамент для підтримки автоматизації взаємодії замовника і виробництва на всіх етапах. Тому, давайте пригальмуємо і спробуємо створити будь-яке замовлення, або подивимося як воно виглядає в численних прикладах, люб'язно наданих розробниками VM. З корисних даних для вирішення поставленого завдання в описувачі замовлення буде тільки поле SKU (артикул) і номер замовлення. Отже, повернемося до картинки опису продукту і розглянемо уважніше поле 'Product SKU'.
ПРИМІТКА: існує думка, що не треба описувати всі властивості продукту в артикулі, тому що він призначений для обробки людиною. Для більшості магазинів з цим твердженням можна погодитися, хоча в загальному випадку допустимою вважається його довжина до 30 символів, що вже не мало. Але в даному випадку нас цікавить максимальна підтримка автоматизації власного виробництва на замовлення, а не перепродаж продукції сторонніх виробників.
Опис формату артикулу (SKU)
Спочатку розглянемо алфавіт, який ми будемо застосовувати. У загальному випадку, оператор магазина може перемикати розкладку клавіатури при введенні інформації, а також, наприклад, диктувати значення артикулу в телефонній розмові. З метою зменшення ймовірності помилок, необхідно обмежити набір допустимих символів. Наприклад, в разі тільки англомовного магазина, ми могли б залішити всі цифри, більшість спеціальних знаків, а також символи латинського алфавіту, крім наступних:
'I' тому що схожий на '1'
'O' тому що схожий на '0'
Але тому що наш магазин багатомовний, то обмеження буде жорсткіше. Дозволяємо всі цифри і символи латинського алфавіту, крім символів кирилиці, накреслення яких схоже на латинські. Зі спеціальних символів залишаемо тільки знак 'мінус' (-), який будемо використовувати для поділу груп символів. Таким чином, список дозволених символів буде наступним:
D, F, G, J, L, N, Q, R, S, U, V, W, Z,-,0...9
Область діяльності передбачуваного підприємства обмежується виробництвом виробів електроніки і програмного забезпечення, тому і артикул будемо розробляти відповідний. Формат артикулу будь-якого виробу буде складатися з заголовка (HD), а також 2-х необов'язкових груп Незалежних (IP) і Залежних Параметрів (DP), завжди розташовуються в наступному порядку:
HD → IP-DP
При цьому, між HD і IP роздільник відсутній, а DP завжди відокремлюється символом «-». Як випливає з назви, до групи Незалежних Параметрів можуть бути віднесені функції пристрою, які не впливають на вибір інших. У той же час, пристрій може містити, наприклад, взаємовиключні для конкретної моделі параметри, які повинні бути виділені в групу Залежних Параметрів.
HD - заголовок має наступну структуру:
Код продукту: 2 цифри |
наприклад, кнопка дверного дзвінка: 01 |
Код моделі: 3 цифри |
наприклад, модель 'Colibry': 001 |
Тип продукту: 1 символ або цифра: |
D - Виріб Електроніки в зборі (наприклад, кнопка дзвінка) R - Друкована Плата з установленими елементами до виробу електроніки Z - порожня Друкована Плата до виробу електроніки S - Програмне Забезпечення |
Таким чином, для одного Виробу Електроніки ми можемо, при необхідності, виділити замовлення запасний друкованої плати або програмного забезпечення.
ПРИМІТКА: хорошим тоном є наявність в заголовку префікса довжиною 2-3 символу, що відображає назву виробника. Наприклад, в моєму випадку можна було-б визначити його як 'APO'. Але, по-перше ці символи заборонені в нашому конкретному алфавіті, а по-друге, бажано щоб кількість символів в артикулі було мінімальним. Тому, я не використовую префікс.
IP - група Незалежних Параметрів для певного типу продукту
Розглянемо його на прикладі Вироби Електроніки (тип продукту «D» за нашою класифікацією), яке завжди оформлено в якийсь корпус:
Матеріал корпусу: 1 символ | L – метал S – пластик W – дерево |
Колір корпусу: 1 символ або цифра | D - білий F - чорний R - червоний G - зелений L - синій N - помаранчевий Q - сірий V - жовтий |
Форма корпусу: 1 символ або цифра | R - прямокутник G - дзвін S - серце |
DP - група Залежних Параметрів
Вона представляє останню частину структури артикулу, яку ми також розглянемо на прикладі Виробу Електроніки 'Кнопка Дверного Дзвінка':
Роздільник: 1 символ | "-" |
Підсвічування кнопки (колір): 1 символ | U - відсутне Z - змінюеться програмно R - червоний G - зелений |
Звук: 1 символ | U - відсутний Q - пьезо-баззер (підходить для простих мелодій) D - динамік (для поліфонії) |
Таким чином артикул 'Кнопки Дверного Дзвінка' моделі 'Colibry' з наступними характеристиками:
Матеріал Корпусу: Пластик
Колір корпусу: Червоний
Форма корпусу: Серце
Підсвічування: Відсутне
Звук: Пьезо
буде описаний 12-ю символами: 01001DSRS-UQ.
Чи можна зробити короткий артикул?
Начебто вкрай простий виріб і раптом таке довге визначення. Ми можемо спробувати скоротити його, якщо звернемося до двійковій системі числення, і перепишемо все вищезгадане в такій формі:
Код продукту: 7 бит |
|
Код моделі продукту: 10 бит | |
Тип продукту: 2 бита | 00 - Виріб Електроніки в зборі (наприклад, кнопка дзвінка) 01 - Друкована Плата з установленими елементами до виробу електроніки 10 - порожня Друкована Плата до виробу електроніки 11 - Програмне Забезпечення |
Матеріал корпусу: 2 бита | 01 – метал 10 – пластик 11 – дерево |
Колір корпусу: 3 бита | 000 - білий 001 - чорний 010 - червоний 011 - зелений 100 - синій 101 - помаранчевий 110 - сірий 111 - жовтий |
Форма корпусу: 2 бита | 00 – прямокутник 01 – дзвін 10 – серце |
Роздільник (-) | В ЦЬОМУ ФОРМАТІ НЕ ВИКОРИСТОВУЄМО |
Підсвічування кнопки (колір): 3 бита | 000 - відсутне 001 - змінюваний програмно 010 - білий 011 - червоний 100 - зелений |
Звук: 2 бита | 00 - відсутній 01 - пьезо-баззер (підходить для простих мелодій) 10 - динамік (для поліфонії) |
Разом 31 біт, які можуть бути представлені у вигляді семи символів по модулю 16 (Hex-format), і тоді артикул нашої 'Кнопки Дверного Дзвінка' моделі 'Colibry' і кодом форми корпусу 0010 буде виглядати так: 1004941. Так, ми скоротили описатель на 5 символів (з яких один роздільник '-' не несе смислового навантаження). А тепер розглянемо інші сторони такого підходу:
- Якщо в першому випадку можна з часом звикнути до формату, то скорочений варіант абсолютно не інформативний для людини
- Hex-format включає символи 'A, B, C, E', які ми виключили з алфавіту артикулу для нашого багатомовного сайту. Значить доведеться використовувати модуль 8, який дасть тільки числове уявлення. Це може здатися навіть зручним, але збільшить розмір артикулу. Для нашого прикладу код перетвориться в 100044501. Тобто скорочення складе вже не 5, а 3 символі.
- При описі різноманітних продуктів в VM, нам доведеться багато разів заповнювати SKU для кожного варіанту, що в разі бітових полів напевно буде приводити до множинних помилок. Символьний формат тут явно виграє.
- Цілком ймовірно, що нам доведеться самостійно складати запити до бази даних VM, які будуть простіши і зрозуміліши, якщо застосовувати символьний формат.
- Для автоматизації обробки замовлень нам потрібен буде спеціалізований програмний парсер, скануючий замовлення на помилки в SKU, а також розподіляє його по процесам виготовлення виробу (вибір друкованої плати, комплектуючих і пошук кращого на даний момент постачальника комплектуючих, компіляція програмного забезпечення відповідно до вимог замовлення і т. д.). У разі бінарного варіанту, нам необхідно буде створювати його самостійно. Для символьного ж варіанту досить, наприклад, скласти JSON-схему необхідного артикулу, і обробити його стандартним парсером.
Таким чином я зупиняю вибір на первинному варіанті опису артикулу.
Реалізація підтримки SKU
Варіант №1
ПРИМІТКА: не поспішайте повторювати описувані події
Повернемося до створеного раніше описателю продукту 'Button' і внесемо такі зміни:
- Змінимо назву на 'Root-Door Bell Button-Colibry', тим самим визначивши цей продукт кореневим, тому що передбачається виготовлення кнопок різних типів. При цьому словосполучення 'Root-' спеціально поставлено на початку, щоб в подальшому легко знаходити все кореневі описатели інших виробів сортуючи або фільтруючи список по полю 'Product Name'.
- В поле SKU внесемо Постійне Значення Заголовка '01001D', яке вказує на те, що це 'Виріб Електроніки' з групи 'Door Bell Button', модель якого має ідентифікатор 'Colibry'. Таким чином, ми створили 2 пари 'назва - цифровий ідентифікатор' (01-Door Bell Button і 001-Colibry), що дозволяє в подальшому легко автоматизувати необхідні перевірки при виробництві, і в той же час не утруднює читання інформації людиною.
- Знімемо позначку з чекбокса 'Published' тому що цей кореневої продукт містить не повний описатель і немає сенсу публікувати його, а значить і переводити описатель на різні мови також не потрібно. У закладці 'Product Status' вкажемо кількість товару рівним 0 (поле 'In Stock'). Зауважимо, що при цьому його 'Product Alias' також буде виключений з URL, але ціна буде входити в розрахунок вартості похідних продуктів. Тому, тут можна вказати деяку постійну частину вартості товару, яка буде присутня в будь-якому продукті, похідному від даного кореневого.
Таким чином, опис батьківського продукту буде мати наступний вигляд:
Тепер ми можемо створювати описатели реальних продуктів, похідних від даного. У цьому ж діалозі натиснемо кнопку 'Add a Child Product' і створимо такий опис:
Змінимо значення в полях 'Product Name' для кожної мови, а також відзначимо чекбокс 'Published'. Зверніть увагу, я присвоїв коротку назву аліасу, тому що VM автоматично додає до нього суфікс '-detail' і це треба враховувати, щоб не перевищити допустиму довжину URL, а також намагатися робити його осмисленим. Таким чином, відносний адреса опису даного продукту англійською мовою буде виглядати наступним чином:
'/en/store/electronics/bells/colibry-detail'
Також я залишив порожніми поля, що стосуються ціни цього дочірнього продукту. Справа в тому, що якщо заповнити їх тут, то VM НЕ буде додавати до загальної вартості базове значення, яке ми вказали для батьківського продукту. У той же час, VM буде це робити якщо ми введемо додаткові користувальницькі поля, за допомогою яких зможемо гнучко варіювати ціну. Як бачите я теж не заповнив поле 'Product SKU', тому що в даному випадку воно не фіксоване і його наповнення залежить від вибору користувача.
Отже, нам необхідно знайти зручні штатні засоби VM для:
- ВИРОБНИЦТВА, щоб легко описувати різноманітні варіанти своїх виробів
- ПОКУПЦЯ, щоб він міг легко вказати свої індивідуальні вимоги до товару з різноманітності, пропонованого нашим виробництвом
Ще раз розглянемо список з 5-ти параметрів, значення яких нам необхідно бачити в артикулі і якими користувач повинен мати можливість керувати при замовленні «Кнопки дзвінка»:
- Матеріал корпусу (3 варіанти)
- Колір корпусу (8 варіантів)
- Форма корпусу (3 варіанти)
- Підсвічування (4 варіанти)
- Звук (3 варіанти)
Загальна кількість варіантів 3 х 8 х 3 х 4 х 3 = 864!
VM пропонує зручну можливість створювати різноманітні користувацькі поля за кількістю параметрів до 5-ти. Але в даному випадку нам це не підходить, тому що занадто велике кількість варіантів. Трудомістким в плані реалізації представлені також створення ієрархічних списків описателей дочірніх продуктів. Адже нам потрібно не тільки створити описатели, а й відображати різноманітні залежності в ціні кінцевого продукту, при цьому генеруючи необхідний SKU.
Варіант №2
Розділимо наші параметри на 2 групи:
Незалежні (IP)
- Матеріал корпусу
- Колір корпусу
- Форма корпусу
Залежні (DP)
- Підсвічування
- Звук
Для кожної IP-групи створимо приховану Custom Fields Group. Наприклад, для «Матеріалу корпусу» вона буде такою:
У кожну подібну групу вкладемо 2 призначених для користувача поля:
1. видиме типу «string» для відображення списку варіантів користувачеві
2. невидиме типу «property», для зберігання патерну SKU, що відповідає даній групі
Для DP-групи створимо стандартне видиме мультиваріантне поле:
ПРИМІТКА: зверніть увагу, що заголовки видимих груп визначені у вигляді багатомовних заміщень, створення яких описано раніше.
На наступному скріншоті представлена частина списку створених груп Полів Користувача:
Тепер можна створити описувач продукту. Для цього в діалозі 'Products' натиснемо кнопку 'New' і опишемо, наприклад, базовий варіант кнопки «Colibry»:
Зверніть увагу на заповнення поля 'Product SKU'. Тут немає даних про матеріал, колір і форму корпусу, але є відомості про відсутність звуку і підсвічування в даному варіанті кнопки. Зберігаємо цю форму (англійську) і редагуємо для кожної мови.
Ну ось і настав час застосувати наші Групи Користувальницьких Полів. Відкриємо відповідну закладку на цій же формі і виберемо групу або поле зі списку, підготовленого нами раніше. Я вибрав першим мультиваріантне поле, яке дозволяє описати обмеження зі спільного застосування звуку і підсвічування, хоча логічніше було б вказати його останнім. Справа в тому, що обробка застосовуваних нами різноманітних списків і списків типу «string» виконана в коді VM різними, і на мій погляд дещо конфліктуючими способами, що призводить до скидання покажчиків у всіх списках типу «string» при оновленні сторінки або зміні елемента вибору в розташованому на цій же сторінці мультиваріантному полі. Якщо списків на сторінці кілька, то це можна не відразу помітити і в підсумку збити користувача з пантелику, коли він натисне кнопку «Помістити в кошик». Я повідомив про це розробникам VM, ну а поки з цієї причини поставив мультиваріантне поле першим в списку в надії, що користувач працює з полями в напрямку зверху-вниз. Нижче показаний приклад заповнення такого поля:
Як бачите, воно додано 2 рази для підтримки описателей звуку і підсвічування. При цьому, списки кількості варіантів значно скорочені для даної моделі (по 2 на кожен параметр). Зверніть увагу, що для будь-якого виду вказується саме ціна, а не зміна до базової ціни і розширення поля «Product SKU» заповнюється в суворій відповідності з описаним раніше шаблоном, і тільки щодо DP-групи.
Далі додаємо елементи IP-групи:
Як бачите дана модель виробу має тільки один тип матеріалу корпусу (VM_ED_BODY_PLASTIC) і ми могли б взагалі не вводити сюди список. Але тому що поруч на сторінці товарів може бути показаний інший тип кнопки, який має розширений список матеріалів (пластик, метал і т.д.), то на мій погляд відмінність в подачі інформації може збити покупця з пантелику. Далі ми бачимо опис 3-х варіантів кольору, два з яких додають до ціни виробу 5 одиниць вартості.
Повернемося до головного. У кожної подібної групи присутнє спеціальне поле типу «Property», вміст якого призначен для вказівки місця розташування і людино-читабельною подання даної частини в загальному паттерне SKU. Таким чином, наприклад, значення «2-D» призначає матеріалу VM_ED_BODY_WHITE символ «D» в паттерне SKU, який повинен бути розміщений другим в IP-частини патерну SKU даного типу продукту.
Відкриємо, фінальний список «Products» щодо нашої кнопки типу «Colibry» - всього 4 позиції:
Це тому що ми визначили для неї наступний список варіантів:
- Матеріал корпусу (1 варіант)
- Колір корпусу (4 варіанти)
- Форма корпусу (1 варіант)
- Підсвічування (2 варіанти)
- Звук (2 варіанти)
Загальна кількість варіантів 1 х 4 х 1 х 2 х 2 = 16. Але, тому що загальна кількість продуктів в списку визначається полями в різноманітної групі, то їх у нас всього 4. Таким чином, для підтримки всіх 864 варіантів, визначених раніше, нам знадобиться описати всього 12 продуктів, тому що:
- Підсвічування (4 варіанти)
- Звук (3 варіанти)
Для покупця картинка також не рясніє різноманіттям варіантів груп і дочірніх підгруп, що дозволяє йому зосередитися на виборі необхідних функцій. Звичайно ж, медіа-елементи будуть присутні, але не нав'язливо:
Спробуємо оформити замовлення:
Як бачимо інформації досить для того, щоб покупець міг переконатися, що всі замовлені властивості підтверджені в словесній формі, і за великим рахунком йому не має значення як виглядає SKU. Для нас же його точне оформлення вкрай важливо, тому що у нас немає співробітників, які читали б кожне замовлення і планували його виконання, розбиваючи на підпроцеси. Тому, необхідно створити заміщення коду VM, яке обробить описані раніше поля типу «Property», і автоматично модифікує SKU відповідним чином в момент оформлення замовлення. На перший погляд це можна зробити в коді компонента, зазначеного на наступному скріншоті:
Невеликий відступ щодо правила, якому я намагаюся слідувати в разі необхідності внесення змін у сторонній код:
«Код заміни або доповнення повинен бути максимально коротким і бажано оформлений в один цілісний блок (тобто бути присутнім тільки в одному місці)»
Це дозволить в подальшому уникнути ситуацій, подібних показаної в гуморесці, де співак приніс на концерт свої ноти, але вони в такому стані, що піаніст не може розібратися в різноманітті позначок «тут грати, а тут не грати»
На жаль, мені не вдалося знайти в цьому компоненті місця, яке відповідає вказаному правилу внесення змін. Довелося зробити це в коді ядра VM і тому що це не стандартне рішення, то приводити його тут не стану. Скажу тільки, що додаток зроблено у вигляді одного короткого блоку коду, який в підсумку дозволяє правильно показати користувачеві всю інформацію, включаючи SKU:
На жаль, VM не робить підстановку багатомовних визначень при показі замовлень адміністратору, але в даному випадку це не велика проблема:
Отже, представлений підхід до опису продукту дозволяє:
- оформляти структуру SKU в єдиному стандартному діалозі VM
- легко змінювати порядок елементів в паттерне SKU і їх значення, незалежно від фізичного розміщення списків на формі
- максимально виключити помилки при описі продукту, тому що SKU заповнюється автоматично при оформленні замовлення
- поєднувати в описувач товару велику кількість списків різного типу
- значно зменшити трудовитрати на опис різних варіантів продукту і його метатегов
Емуляція поштового агента
При підтвердженні замовлення, VM відправляє електронні листи покупцеві і продавцеві. Оскільки ми ведемо розробку на локальному сервері, то в цей момент відбудеться помилка відправки пошти. Необхідно самостійно встановити і налаштувати відповідне програмне забезпечення. У разі Linux це зазвичай 'sendmail'. Але я для цієї мети використовую найпростіший емулятор невідомого програміста, який знайшов в коментарях до однієї зі статей в Інтернеті. Ось його код:
#!/bin/sh
prefix="/var/www/sendmail"
date='date \+\%Y\%m\%d\%H\%M\%N'
name="$prefix/$date.eml"
while IFS=read line
do
echo "$line" >> $name
done
chmod 666 $name
Помістіть його в файл, наприклад, під назвою 'fake_sendmail.sh' і збережіть в директорії '/usr/sbin/sendmail', присвоївши йому атрибут 'executable'. Створіть директорію 'sendmail' як зазначено в змінної 'prefix' коду. Вкажіть значення шляху до даного файлу 'sendmail' в 'php.ini':
sendmail_path = /usr/sbin/sendmail/fake_sendmail.sh
Відкрийте закладку 'Server' в діалозі Joomla! 'Global Configuration', і виберіть 'Sendmail' в якості поштового агента:
Тепер поштові повідомлення будуть зберігатися в директорії 'sendmail' і їх можна переглядати стандартними засобами. Наприклад, так виглядає лист підтвердження відправки замовлення в 'Thunderbird Mail':

Инструменти і документи
Операційна система: | Linux (наприклад http://www.ubuntu.com/download) |
Програми: | LAMP (наприклад https://bitnami.com/stack/lamp) CMS Joomla! (https://www.joomla.org/) VirtueMart (http://extensions.joomla.org/extensions/extension/e-commerce/shopping-cart/virtuemart) |
Опціонально: | Netbeans (https://netbeans.org/downloads/) |
Додаткове читання: |
Apache HTTP Server (https://httpd.apache.org/docs/2.4) |