Вам нужно добавить форму обратной связи на сайт? Создать форму регистрации, обработать опрос, собрать заявку на консультацию? Обычно это превращается в квест: свёрстай HTML, напиши JavaScript для валидации, создай PHP-скрипт обработки, настрой отправку на email, не забудь про безопасность... И так каждый раз для каждой новой формы.
А что если просто написать HTML-форму в шаблоне, добавить пару строк PHP-кода для валидации — и всё? Форма работает, данные проверены, письмо отправлено, информация сохранена в базе.
В Wepps Platform работа с формами организована как конвейер: вы описываете форму в шаблоне, система автоматически собирает данные, валидирует их, показывает ошибки и обрабатывает успешную отправку. Давайте разберёмся, как это работает и почему это намного проще, чем кажется.
Конвейер обработки форм: как это понять
Представьте, что форма на сайте — это производственная линия на заводе. У вас есть:
-
Шаблон формы (HTML) — это чертёж изделия. Вы описываете, какие поля нужны (имя, email, телефон), какие типы данных (текст, файл, чекбокс). Smarty-шаблон рисует форму на странице.
-
JavaScript (Forms.js) — это контроль качества на входе. Проверяет базовые вещи: заполнены ли обязательные поля, не пустая ли форма. Отправляет данные на сервер через AJAX.
-
Request.php — это главный цех обработки. Получает данные, проверяет их серьёзно (валидация email, телефона), решает что делать: отправить письмо, сохранить в базу, вернуть ошибку.
-
Validator — это отдел технического контроля. Проверяет каждое поле по правилам и говорит: "Это email неправильный", "Телефон должен быть из 10 цифр", "Поле пустое".
-
Обратная связь пользователю — готовое изделие. Показывает красные подсветки у неправильных полей или зелёное сообщение "Спасибо, ваше сообщение отправлено!".
Или вспомните ресторан:
- Шаблон формы — это меню, где клиент делает заказ
- JavaScript — официант, который сразу говорит "Выберите хотя бы одно блюдо"
- Request.php — кухня, где готовят заказ
- Validator — шеф-повар, который проверяет качество ингредиентов
Суть в том, что вы просто описываете форму, а платформа берёт на себя всю техническую работу.
Что такое FormWepps? Ваш личный менеджер форм
FormWepps — это JavaScript-класс, который управляет всеми формами на сайте. Его главная задача — собрать данные из формы и отправить на сервер, не перезагружая страницу.
Суперсилы FormWepps:
-
Отправка через AJAX. Страница не перезагружается, пользователь остаётся на месте. Современно и удобно.
- На практике: пользователь нажал "Отправить" → данные улетели на сервер → через секунду появилось "Сообщение отправлено" — и всё это без белого экрана загрузки.
-
Загрузка файлов. Прикрепить резюме, фото, документ — всё работает автоматически.
- На практике: выбрал файл → он сразу загрузился в сессию → при отправке формы файл прикрепится к письму.
-
Автоматическая очистка ошибок. Показал ошибки в полях → пользователь начал исправлять → ошибки исчезли.
Где вы это видите на любом сайте?
- Форма "Заказать звонок" в модальном окне
- Форма обратной связи в футере
- Форма регистрации с загрузкой аватара
- Опрос с чекбоксами и радиокнопками
Что такое Validator? Контролёр качества данных
Validator — это PHP-класс с набором методов для проверки данных. Если FormWepps — это почтальон, который доставляет письмо, то Validator — это таможня, которая проверяет содержимое.
Суперсилы Validator:
- Проверка типов данных. Email это email, телефон это телефон, число это число — никакой самодеятельности.
- Визуализация ошибок. Автоматически генерирует JavaScript, который подсвечивает неправильные поля красным и показывает текст ошибки.
- Гибкие проверки. От простых "поле не пустое" до сложных "это валидный штрих-код EAN13".
Проще простого: Вы пишете Validator::isEmail($email, "Неверный email") — и класс либо вернёт пустую строку (всё ок), либо текст ошибки.
Что такое Request? Мозг обработки форм
Request — это абстрактный класс, от которого наследуются все обработчики форм. Он организует весь процесс: получает данные, вызывает валидацию, подключает шаблоны ответа.
Суперсилы Request:
- Автоматический сбор данных. Все переменные из
$_REQUESTпопадают в$this->getуже очищенными от лишних пробелов. - Встроенная работа с шаблонами. Можете вернуть HTML-ответ через Smarty-шаблон.
- Метод
outer(). Один вызов — и готов JavaScript с ошибками или сообщением успеха.
Магия в соединении: создаём рабочую форму за 5 шагов
Давайте создадим форму обратной связи с нуля:
Шаг 1. Создаём HTML-форму в шаблоне
В файле Contacts.tpl пишем:
<form action="javascript:formWepps.send('feedback','feedback-form','/ext/Contacts/Request.php')"
id="feedback-form" class="w_form">
<h2>Напишите сообщение</h2>
<fieldset>
<section>
<div class="title">Ваше имя</div>
<label class="w_label w_input w_require">
<input type="text" name="name" placeholder="" />
</label>
</section>
<section>
<div class="title">Email</div>
<label class="w_label w_input w_require">
<input type="email" name="email" placeholder="" />
</label>
</section>
<section>
<div class="title">Сообщение</div>
<label class="w_label w_area w_require">
<textarea name="comment" placeholder=""></textarea>
</label>
</section>
</fieldset>
<fieldset>
<section>
<label class="w_label w_checkbox">
<input type="checkbox" name="approve" />
<span>Я согласен на обработку персональных данных</span>
</label>
<label class="w_label w_button">
<input type="submit" value="Отправить" disabled />
</label>
</section>
</fieldset>
</form>
Ключевые моменты:
action="javascript:formWepps.send(...)"— отправка через AJAXid="feedback-form"— уникальный ID формы для обработки ошибокname="name",name="email"— эти имена будут ключами в PHP-массиве$this->getclass="w_require"— визуальная пометка обязательных полейdisabledна кнопке — активируется только после согласия с обработкой данных
Шаг 2. Создаём обработчик Request.php
В файле packages/WeppsExtensions/Contacts/Request.php:
<?php
require_once '../../../configloader.php';
use WeppsCore\Request;
use WeppsCore\Validator;
use WeppsCore\Connect;
use WeppsExtensions\Addons\Messages\Mail\Mail;
class RequestContacts extends Request
{
public function request($action = '')
{
switch ($action) {
case 'feedback':
$this->feedback();
break;
default:
Exception::error404();
break;
}
}
private function feedback()
{
// Валидация полей
$this->errors = [];
$this->errors['name'] = Validator::isNotEmpty($this->get['name'], "Не заполнено");
$this->errors['email'] = Validator::isEmail($this->get['email'], "Неверный формат email");
$this->errors['comment'] = Validator::isNotEmpty($this->get['comment'], "Не заполнено");
// Показываем ошибки или сообщение успеха
$outer = Validator::setFormErrorsIndicate($this->errors, $this->get['form']);
$this->assign('jscode', $outer['html']);
// Если ошибок нет — обрабатываем
if ($outer['count'] == 0) {
// Формируем сообщение
$subject = "Сообщение с сайта";
$message = "Имя: {$this->get['name']}\n";
$message .= "Email: {$this->get['email']}\n";
$message .= "Сообщение: {$this->get['comment']}\n";
// Сохраняем в базу
$row = [
'Name' => trim($this->get['name']),
'Email' => $this->get['email'],
'Descr' => trim($message),
'SDate' => date("Y-m-d H:i:s"),
'SGroup' => 'Обратная связь'
];
Connect::$instance->insert("FormsData", $row);
// Отправляем письмо
$mail = new Mail('html');
$mail->mail(Connect::$projectInfo['email'], $subject, nl2br($message));
// Показываем успех
$arr = Validator::setFormSuccess("Спасибо! Ваше сообщение отправлено", $this->get['form']);
$this->assign('jscode', $arr['html']);
}
$this->tpl = "RequestContacts.tpl";
}
}
$request = new RequestContacts($_REQUEST);
$smarty->assign('get', $request->get);
$smarty->display($request->tpl);
Шаг 3. Создаём шаблон ответа RequestContacts.tpl
{$jscode}
Всё! Этот минималистичный шаблон выводит JavaScript-код с ошибками или сообщением успеха.
Шаг 4. Подключаем JavaScript и стили
В основном классе расширения Contacts.php:
$this->headers->js("/ext/Template/Forms/Forms.{$this->rand}.js");
$this->headers->css("/ext/Template/Forms/Forms.{$this->rand}.css");
Класс FormWepps уже реализован в Forms.js — не нужно ничего писать!
Шаг 5. Готово!
Теперь форма:
- ✅ Проверяет обязательные поля
- ✅ Валидирует email
- ✅ Отправляет данные без перезагрузки
- ✅ Показывает ошибки красным цветом рядом с полями
- ✅ Сохраняет данные в таблицу
FormsData - ✅ Отправляет письмо на email администратора
- ✅ Показывает "Спасибо, сообщение отправлено!"
Вот и вся магия! Вы описали форму в HTML, добавили 3 строки валидации, указали что делать с данными — и готово. Остальное платформа сделала сама.
Почему это круто? Выгоды для всех
🚀 Для владельца бизнеса:
- Быстрое добавление форм. Новая форма — это несколько часов, а не дней разработки.
- Все заявки в одном месте. Таблица
FormsDataхранит все обращения с разных форм. - Письма на email. Дублирование в почту — ничего не потеряется.
- Готовые стили. Формы выглядят современно из коробки (классы
w_form,w_label,w_input).
👨💻 Для разработчика:
- Не нужно писать AJAX каждый раз.
FormWepps— это глобальный объект, доступный везде. - Валидация за 1 строку.
Validator::isEmail()вместо регулярных выражений и проверок. - Автоматическая визуализация ошибок. Метод
setFormErrorsIndicate()генерирует весь JavaScript. - Загрузка файлов из коробки. Просто
<input type="file">— и всё работает. - Безопасность. Все данные очищаются от пробелов через
Utils::trim(). - Гибкость настройки. Полный контроль над HTML-разметкой через
.tplшаблоны. - Единая структура. Все формы следуют одному паттерну — легко поддерживать и масштабировать.
👥 Для администратора контента:
- Все заявки в одном месте. Таблица
FormsDataв админке показывает все обращения с разных форм сайта. - Просмотр вложений. Если клиент прикрепил файлы (резюме, документы) — они доступны прямо из админки.
- Удобная фильтрация. Поиск по дате, группе формы (обратная связь, заявки, подписки), статусу обработки.
- Экспорт данных. Выгрузка заявок в Excel для анализа и отчётов.
✅ Для всех вместе:
- Единый стандарт. Все формы на сайте работают одинаково — клиенты привыкают, меньше ошибок.
- Мобильная адаптация. Стили
w_formадаптивны по умолчанию. - Доступность. Правильная разметка с
<label>для всех полей. - Масштабируемость. Одна форма или 50 форм — подход не меняется.
Реальные сценарии использования
Сценарий 1: Форма "Заказать звонок" в модальном окне
Ситуация: Нужна быстрая форма в popup с двумя полями: имя и телефон.
Решение:
<form action="javascript:formWepps.popup('callback','callback-form','/ext/Contacts/Request.php')"
id="callback-form">
<label class="w_label w_input w_require">
<input type="text" name="name" placeholder="Ваше имя" />
</label>
<label class="w_label w_input w_require">
<input type="text" name="phone" placeholder="+7 (___) ___-__-__" />
</label>
<label class="w_label w_button">
<input type="submit" value="Заказать звонок" />
</label>
</form>
Добавляем в Request.php:
case 'callback':
$this->errors['name'] = Validator::isNotEmpty($this->get['name'], "Укажите имя");
$this->errors['phone'] = Validator::isNotEmpty($this->get['phone'], "Укажите телефон");
// ... обработка
Результат: Форма в popup, маска на телефон (через inputmask.js), данные в базу, уведомление на email — за 15 минут.
Сценарий 2: Добавление поля загрузки файла
Ситуация: Нужно добавить в форму возможность загрузить файл (резюме, документ, фото).
Решение: Добавьте в форму секцию с полем загрузки файла:
<section>
<div class="title">Резюме</div>
<label class="w_label w_upload">
<input type="file" name="resume-upload" />
<span>Прикрепить файл (PDF, DOC, DOCX)</span>
</label>
<div class="w_upload_add">
{foreach $uploaded['resume-upload'] as $k => $file}
<div class="w_upload_file" data-key="{$k}">
{$file.name} <i class="bi bi-x-circle-fill"></i>
</div>
{/foreach}
</div>
</section>
В PHP:
$files = new Files();
if ($filesAttach = $files->getUploaded($this->get['form'], 'resume-upload')) {
$mail->setAttach($filesAttach);
}
$mail->mail($email, $subject, $message);
$files->removeUploaded($this->get['form'], 'resume-upload');
Результат: Файл загружается в сессию при выборе, прикрепляется к письму при отправке, автоматически удаляется после.
Сценарий 3: Сложная форма с чекбоксами, радио, селектами
Ситуация: Опросник с разными типами полей.
Решение:
<fieldset>
<section>
<div class="title">Интересующие услуги</div>
<label class="w_label w_checkbox">
<input type="checkbox" name="services[]" value="web"> <span>Разработка сайтов</span>
</label>
<label class="w_label w_checkbox">
<input type="checkbox" name="services[]" value="seo"> <span>SEO-продвижение</span>
</label>
</section>
<section>
<div class="title">Бюджет проекта</div>
<label class="w_label w_radio">
<input type="radio" name="budget" value="small"> <span>До 100 000 ₽</span>
</label>
<label class="w_label w_radio">
<input type="radio" name="budget" value="medium"> <span>100 000 - 500 000 ₽</span>
</label>
</section>
<section>
<div class="title">Срочность</div>
<label class="w_label w_select">
<select name="urgency">
<option value="month">В течение месяца</option>
<option value="week">Срочно, неделя</option>
</select>
</label>
</section>
</fieldset>
В PHP:
// Массив чекбоксов
if (!empty($this->get['services'])) {
$services = implode(', ', $this->get['services']);
$message .= "Услуги: $services\n";
}
// Радио и селект — обычные переменные
$message .= "Бюджет: {$this->get['budget']}\n";
$message .= "Срочность: {$this->get['urgency']}\n";
Результат: Все типы полей работают, массивы обрабатываются автоматически, Select2 подключается для красивых селектов.
Частые вопросы и заблуждения
❓ Нужно ли писать JavaScript для каждой формы?
Заблуждение: Для каждой новой формы нужно писать свой обработчик на JavaScript.
Реальность: Нет! Класс FormWepps — глобальный объект, доступный на всех страницах. Вы просто указываете formWepps.send('action', 'form-id', '/путь/к/Request.php') в атрибуте action формы — и всё. JavaScript для загрузки файлов, очистки ошибок, работы с чекбоксами — уже написан один раз для всех форм.
❓ Как защититься от спама и ботов?
Заблуждение: Формы в платформе не защищены от автоматических отправок.
Реальность: Есть несколько уровней защиты:
- Honeypot — добавьте скрытое поле
<input type="text" name="honeypot" style="display:none">. В PHP проверяйте: если оно заполнено — это бот. - Временные метки — сохраняйте в сессии время показа формы, проверяйте что прошло хотя бы 3 секунды.
- reCAPTCHA — подключается через класс расширения.
Пример honeypot:
if (!empty($this->get['honeypot'])) {
return; // Бот, игнорируем
}
❓ Можно ли отправить форму БЕЗ AJAX (обычным POST)?
Ответ: Да, но не рекомендуется. Просто уберите javascript: из action:
<form action="/ext/Contacts/Request.php" method="POST">
Но тогда:
- ❌ Страница перезагрузится
- ❌ Ошибки не подсветятся красным автоматически
- ❌ Пользователь увидит белый экран во время обработки
AJAX-подход современнее и удобнее.
Сравнение: традиционный подход vs Wepps Platform
| Аспект | Традиционный подход | Wepps Platform |
|---|---|---|
| Создание формы | HTML + jQuery validation + AJAX-запрос + PHP-обработка | HTML + formWepps.send() — готово ✅ |
| Валидация | Писать регулярки или использовать библиотеку | Validator::isEmail() — одна строка ✅ |
| Показ ошибок | Писать JS для подсветки полей красным | setFormErrorsIndicate() — автоматически ✅ |
| Загрузка файлов | Настройка FormData, проверка размера, MIME-типов | <input type="file"> — работает из коробки ✅ |
| Сохранение в БД | Писать SQL-запросы, защищаться от инъекций | Connect::$instance->insert($table, $row) ✅ |
| Отправка email | Настройка PHPMailer или SwiftMailer | $mail->mail($to, $subject, $message) ✅ |
| Время разработки | 4-8 часов на форму | 30 минут - 1 час ✅ |
Пошаговое руководство для начинающих
Шаг 1: Определите поля формы
Запишите на бумаге или в блокноте:
- Какие данные нужно собрать? (имя, email, телефон, сообщение)
- Какие поля обязательные? (name, email — обязательно; телефон — опционально)
- Нужна ли загрузка файлов? (да/нет)
Шаг 2: Создайте HTML-разметку в .tpl файле
Используйте шаблон:
<form action="javascript:formWepps.send('myaction','myform','/ext/MyExtension/Request.php')"
id="myform" class="w_form">
<fieldset>
<section>
<div class="title">Название поля</div>
<label class="w_label w_input w_require">
<input type="text" name="fieldname" />
</label>
</section>
<!-- ... другие поля ... -->
</fieldset>
<fieldset>
<label class="w_label w_button">
<input type="submit" value="Отправить" />
</label>
</fieldset>
</form>
Типы полей:
w_input+<input type="text">— текстовое полеw_area+<textarea>— многострочное полеw_checkbox+<input type="checkbox">— чекбоксw_radio+<input type="radio">— радиокнопкаw_select+<select>— выпадающий списокw_upload+<input type="file">— загрузка файла
Шаг 3: Создайте или откройте Request.php
Структура:
<?php
require_once '../../../configloader.php';
use WeppsCore\Request;
use WeppsCore\Validator;
use WeppsCore\Connect;
class RequestMyExtension extends Request
{
public function request($action = '')
{
switch ($action) {
case 'myaction':
$this->myaction();
break;
default:
Exception::error404();
break;
}
}
private function myaction()
{
// Здесь будет код обработки
$this->tpl = "RequestMyExtension.tpl";
}
}
$request = new RequestMyExtension($_REQUEST);
$smarty->assign('get', $request->get);
$smarty->display($request->tpl);
Шаг 4: Добавьте валидацию полей
Внутри метода myaction():
$this->errors = [];
$this->errors['name'] = Validator::isNotEmpty($this->get['name'], "Укажите имя");
$this->errors['email'] = Validator::isEmail($this->get['email'], "Неверный email");
$outer = Validator::setFormErrorsIndicate($this->errors, $this->get['form']);
$this->assign('jscode', $outer['html']);
Доступные методы Validator:
isNotEmpty($var, $msg)— поле не пустоеisEmail($var, $msg)— валидный emailisInt($var, $msg)— целое числоisFloat($var, $msg)— число с плавающей точкойisUrl($var, $msg)— корректный URLisPhone($var, $msg)— телефон (10 цифр)isDate($var, $msg)— корректная дата
Шаг 5: Обработайте успешную отправку
Если ошибок нет ($outer['count'] == 0):
if ($outer['count'] == 0) {
// Сохраните в базу
$row = [
'Name' => $this->get['name'],
'Email' => $this->get['email'],
'SDate' => date("Y-m-d H:i:s")
];
Connect::$instance->insert("FormsData", $row);
// Отправьте письмо
$mail = new Mail('html');
$message = "Имя: {$this->get['name']}\nEmail: {$this->get['email']}";
$mail->mail('admin@site.ru', 'Новая заявка', nl2br($message));
// Покажите успех
$arr = Validator::setFormSuccess("Спасибо! Ваша заявка принята", $this->get['form']);
$this->assign('jscode', $arr['html']);
}
Шаг 6: Создайте минимальный шаблон ответа
Файл RequestMyExtension.tpl:
{$jscode}
Шаг 7: Подключите стили и скрипты в основном классе
В файле MyExtension.php:
$this->headers->js("/ext/Template/Forms/Forms.{$this->rand}.js");
$this->headers->css("/ext/Template/Forms/Forms.{$this->rand}.css");
Шаг 8: Протестируйте форму
- Откройте страницу с формой
- Попробуйте отправить пустую форму — должны появиться красные подсветки
- Заполните неправильно email — должна появиться ошибка "Неверный email"
- Заполните правильно — должно появиться "Спасибо! Ваша заявка принята"
- Проверьте таблицу
FormsDataв базе — там должна быть новая запись - Проверьте почту — должно прийти письмо
Совет: Включите режим разработки в config.php ('debug' => 1), чтобы видеть все ошибки PHP.
Принципы работы с формами
✅ Делайте так:
-
Используйте уникальные ID форм — каждая форма должна иметь свой
id, чтобы ошибки подсвечивались правильно.<form id="feedback-form"> <!-- Уникальный ID --> <form id="callback-form"> <!-- Другой ID --> -
Добавляйте класс
w_requireк обязательным полям — пользователь увидит красную звёздочку.<label class="w_label w_input w_require"> <input type="text" name="email" /> </label> -
Всегда оборачивайте input в label — это улучшает доступность и удобство клика.
<!-- ✅ Правильно --> <label class="w_label w_input"> <input type="text" name="name" /> </label> <!-- ❌ Неправильно --> <input type="text" name="name" /> -
Используйте говорящие имена полей —
name="user_email"лучше, чемname="field1".$this->errors['user_email'] = Validator::isEmail($this->get['user_email'], "Неверный email");
❌ Не делайте так:
-
Не дублируйте ID форм — если на странице две формы с
id="form", ошибки будут показываться неправильно. -
Не используйте методы валидации неправильно —
isEmail()для телефона илиisInt()для строки вернут ошибки.// ❌ Неправильно $this->errors['phone'] = Validator::isEmail($this->get['phone'], "Ошибка"); // ✅ Правильно $this->errors['phone'] = Validator::isPhone($this->get['phone'], "Неверный формат телефона"); -
Не забывайте про
$outer['count'] == 0— иначе код выполнится даже при наличии ошибок.// ❌ Плохо Connect::$instance->insert("FormsData", $row); // Выполнится всегда! // ✅ Хорошо if ($outer['count'] == 0) { Connect::$instance->insert("FormsData", $row); }
Типичные ошибки и как их избежать
Ошибка 1: Форма не отправляется, кнопка неактивна
Что происходит: Кнопка отправки остаётся серой (disabled), форма не реагирует на клик.
Причина: Не снята галочка с чекбокса "Согласие на обработку данных", или отсутствует JavaScript для активации кнопки.
Как исправить:
// Этот код уже есть в Forms.js, но если у вас своя форма:
$('input[name="approve"]').on('change', function () {
let isChecked = $(this).prop('checked');
$(this).closest('form').find('input[type="submit"]').prop('disabled', !isChecked);
});
Как избежать: Используйте стандартные классы и структуру форм — тогда formsInit() из Forms.js автоматически всё настроит.
Ошибка 2: Ошибки не подсвечиваются красным
Что происходит: Форма отправляется, но неправильные поля не подсвечиваются, ошибки не видны.
Причина:
- Не подключён
Forms.css(там стили.w_error,.w_error_parent) - Неправильный
idформы в вызовеsetFormErrorsIndicate() - Имена полей в HTML не совпадают с ключами в
$this->errors
Как исправить:
// Проверьте, что form = id формы
$outer = Validator::setFormErrorsIndicate($this->errors, $this->get['form']);
// ^^^^^^^^^^^^^^^^
// Это значение приходит из JavaScript: formWepps.send('action', 'form-id', ...)
// ^^^^^^^^^
<!-- В HTML -->
<form id="feedback-form">
<input type="text" name="email" />
</form>
<!-- В JavaScript -->
<form action="javascript:formWepps.send('feedback','feedback-form','/...')">
^^^^^^^^^^^^^^^
// В PHP — ключ массива = name поля
$this->errors['email'] = Validator::isEmail($this->get['email'], "Ошибка");
// ^^^^^ ^^^^^
Как избежать: Всегда используйте одинаковые имена: name атрибут → ключ в $this->errors → ключ в $this->get.
Ошибка 3: Файлы не загружаются или не прикрепляются к письму
Что происходит: Выбрали файл, но он не появляется в списке загруженных, или письмо приходит без вложения.
Причина:
- Не подключён JavaScript
Forms.js(там обработчик загрузки файлов) - Не настроена сессия (
session_start()должен быть в началеRequest.php) - Не вызван метод удаления файлов после отправки
Как исправить:
// В начале Request.php
if (!session_id()) {
session_start();
}
// При отправке письма
use WeppsExtensions\Addons\Files\Files;
$files = new Files();
if ($filesAttach = $files->getUploaded($this->get['form'], 'file-field-name')) {
$mail->setAttach($filesAttach);
}
$mail->mail($email, $subject, $message);
$files->removeUploaded($this->get['form'], 'file-field-name'); // Удаляем из сессии!
Как избежать:
- Всегда стартуйте сессию в
Request.php - Используйте правильное имя поля (
name="file-field-name") - Удаляйте файлы после обработки, чтобы они не накапливались в сессии
Производительность
Оптимизация: кэширование списка форм
Если у вас на сайте много форм с одинаковыми данными (например, список городов в селекте), не запрашивайте данные при каждом рендере:
// ❌ Неоптимально — запрос к БД при каждой загрузке страницы
$obj = new Data("Cities");
$cities = $obj->fetch("IsHidden=0");
$smarty->assign('cities', $cities);
// ✅ Оптимально — кэширование через Memcached
$cacheKey = "cities_list";
$cities = Connect::$memcached->get($cacheKey);
if (!$cities) {
$obj = new Data("Cities");
$cities = $obj->fetch("IsHidden=0");
Connect::$memcached->set($cacheKey, $cities, 3600); // Кэш на 1 час
}
$smarty->assign('cities', $cities);
Оптимизация: минимизация CSS/JS форм
В режиме продакшн ('debug' => 0 в config.php) платформа автоматически минифицирует и кэширует CSS/JS. Но вы можете ускорить загрузку, объединив несколько файлов:
// Объединяем стили форм и валидации в один файл
$this->headers->css("/ext/Template/Forms/FormsBundle.{$this->rand}.css");
Оптимизация: отложенная загрузка Select2
Если на странице нет селектов, не подключайте библиотеку:
// В основном классе расширения
if ($hasSelects) { // Флаг наличия селектов
$this->headers->js("/packages/vendor/select2/select2/dist/js/select2.full.min.js");
}
Безопасность
Защита от SQL-инъекций
Проблема: Данные из форм могут содержать вредоносный SQL-код.
Решение: Используйте методы класса Connect, которые используют подготовленные запросы (prepared statements):
// ❌ Небезопасно — прямой SQL-запрос
$name = $this->get['name'];
Connect::$instance->db->query("INSERT INTO FormsData (Name) VALUES ('$name')");
// ✅ Безопасно — метод insert() использует prepared statements
$row = ['Name' => $this->get['name']];
Connect::$instance->insert("FormsData", $row);
Защита от XSS-атак
Проблема: Пользователь может ввести <script>alert('XSS')</script> в поле формы.
Решение: Экранируйте вывод в шаблонах Smarty:
{* ❌ Небезопасно — выводится как есть *}
{$get.name}
{* ✅ Безопасно — экранируется автоматически *}
{$get.name|escape}
Для email-сообщений используйте htmlspecialchars():
// ❌ Небезопасно
$message = "Имя: {$this->get['name']}";
// ✅ Безопасно
$message = "Имя: " . htmlspecialchars($this->get['name'], ENT_QUOTES, 'UTF-8');
Защита от CSRF-атак
Проблема: Злоумышленник может отправить форму от имени пользователя с другого сайта.
Решение: Добавьте CSRF-токен в форму:
// В основном классе расширения (при рендере формы)
if (!isset($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
$smarty->assign('csrf_token', $_SESSION['csrf_token']);
<!-- В шаблоне формы -->
<input type="hidden" name="csrf_token" value="{$csrf_token}" />
// В Request.php (при обработке)
if (!isset($_SESSION['csrf_token']) || $this->get['csrf_token'] !== $_SESSION['csrf_token']) {
$this->errors['_general'] = "Ошибка безопасности. Попробуйте еще раз.";
// ... показываем ошибку и выходим
return;
}
Интеграция с другими компонентами
Работа с расширением Files (загрузка файлов)
use WeppsExtensions\Addons\Files\Files;
// Получить загруженные файлы из сессии
$files = new Files();
$uploaded = $files->getUploaded($formId, $fieldName);
// Вернёт массив: [['name' => 'file.pdf', 'path' => '/files/...', ...], ...]
// Прикрепить к письму
if ($filesAttach = $files->getUploaded($this->get['form'], 'resume')) {
$mail->setAttach($filesAttach);
}
// Удалить из сессии после обработки
$files->removeUploaded($this->get['form'], 'resume');
// Передать список загруженных файлов в шаблон (для отображения)
if (isset($_SESSION['uploads'][$formId])) {
$smarty->assign('uploaded', $_SESSION['uploads'][$formId]);
}
Работа с расширением Mail (отправка писем)
use WeppsExtensions\Addons\Messages\Mail\Mail;
// Создать объект письма (тип: text или html)
$mail = new Mail('html');
// Отправить простое письмо
$mail->mail(
'client@example.com', // Кому
'Ваш заказ принят', // Тема
'<p>Спасибо за заказ!</p>' // Сообщение (HTML)
);
// Отправить письмо с вложениями
$mail->setAttach([
['path' => '/files/lists/invoice.pdf', 'name' => 'Счет.pdf'],
['path' => '/files/lists/contract.doc', 'name' => 'Договор.doc']
]);
$mail->mail('client@example.com', 'Документы', $message);
// Отправить письмо с копией
$mail->mail(
'client@example.com', // Основной получатель
'Уведомление',
$message,
'admin@site.ru' // Копия администратору
);
Работа с Telegram (отправка уведомлений в Telegram)
use WeppsExtensions\Addons\Messages\Telegram\Telegram;
// Отправить уведомление в Telegram-канал или чат
$telegram = new Telegram();
$message = "🔔 Новая заявка!\n\n";
$message .= "Имя: {$this->get['name']}\n";
$message .= "Email: {$this->get['email']}\n";
$message .= "Телефон: {$this->get['phone']}";
$telegram->send($message);
// Отправится на chat_id, указанный в config.php: Connect::$projectServices['telegram']
Заключение
Формы в Wepps Platform предоставляют:
- ✅ Готовый JavaScript-класс
FormWeppsдля AJAX-отправки - ✅ Полный набор валидаторов в классе
Validator - ✅ Автоматическую визуализацию ошибок с подсветкой полей
- ✅ Загрузку файлов через сессии без дополнительного кода
- ✅ Интеграцию с отправкой email и Telegram-уведомлений
- ✅ Безопасность через подготовленные запросы и экранирование
Создание новой формы — это не квест, а простой процесс из 5 шагов: HTML-разметка → валидация в PHP → обработка данных → шаблон ответа → готово. Не нужно каждый раз изобретать велосипед, писать AJAX-обработчики или регулярки для email — платформа уже сделала это за вас.
Начните с простой формы обратной связи из раздела "Магия в соединении", экспериментируйте с типами полей, добавляйте загрузку файлов — и через час у вас будет работающая, безопасная, красивая форма.
Файлы:
packages/WeppsCore/Validator.php— класс валидацииpackages/WeppsCore/Request.php— базовый класс обработчиковpackages/WeppsExtensions/Template/Forms/Forms.js— JavaScript для формpackages/WeppsExtensions/Template/Forms/Forms.css— стили формpackages/WeppsExtensions/Contacts/Request.php— пример обработчика
