Реализация контактной формы
Контактная форма — базовый элемент связи с пользователями. Минимальный набор: поля (имя, email, сообщение), защита от спама, подтверждение отправки, email уведомление получателю.
Laravel: обработка формы
class ContactController extends Controller
{
public function store(ContactRequest $request): RedirectResponse|JsonResponse
{
// Сохранить обращение в БД
$inquiry = ContactInquiry::create([
'name' => $request->name,
'email' => $request->email,
'phone' => $request->phone,
'subject' => $request->subject,
'message' => $request->message,
'ip' => $request->ip(),
'user_agent' => $request->userAgent(),
]);
// Отправить уведомление менеджерам
Mail::to(config('mail.contact_recipients'))
->send(new ContactInquiryMail($inquiry));
// Автоответ отправителю
Mail::to($inquiry->email)
->send(new ContactAutoReplyMail($inquiry));
if ($request->expectsJson()) {
return response()->json(['message' => 'Ваше сообщение отправлено']);
}
return back()->with('success', 'Спасибо! Мы свяжемся с вами в течение 24 часов.');
}
}
// app/Http/Requests/ContactRequest.php
class ContactRequest extends FormRequest
{
public function rules(): array
{
return [
'name' => 'required|string|max:100',
'email' => 'required|email:rfc,dns|max:255',
'phone' => 'nullable|string|max:20',
'subject' => 'nullable|string|max:200',
'message' => 'required|string|min:10|max:5000',
];
}
public function messages(): array
{
return [
'name.required' => 'Введите ваше имя',
'email.required' => 'Введите email',
'email.email' => 'Некорректный формат email',
'message.required' => 'Напишите сообщение',
'message.min' => 'Сообщение слишком короткое (минимум 10 символов)',
];
}
}
Rate limiting и защита от спама
// routes/web.php
Route::post('/contact', [ContactController::class, 'store'])
->middleware(['throttle:5,60']); // 5 отправок в час с одного IP
// В ContactRequest
public function withValidator(Validator $validator): void
{
$validator->after(function (Validator $v) {
// Honeypot поле: боты заполняют скрытые поля
if ($this->input('website')) { // hidden поле, люди не заполняют
$v->errors()->add('spam', 'Обнаружен спам');
}
});
}
React: форма с валидацией
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
const schema = z.object({
name: z.string().min(2, 'Введите имя').max(100),
email: z.string().email('Некорректный email'),
message: z.string().min(10, 'Минимум 10 символов').max(5000),
website: z.string().max(0), // honeypot
});
type FormData = z.infer<typeof schema>;
export function ContactForm() {
const { register, handleSubmit, formState: { errors, isSubmitting }, reset } = useForm<FormData>({
resolver: zodResolver(schema),
});
const [success, setSuccess] = useState(false);
const onSubmit = async (data: FormData) => {
await api.post('/contact', data);
setSuccess(true);
reset();
};
if (success) {
return <p role="status">Спасибо! Мы свяжемся с вами в течение 24 часов.</p>;
}
return (
<form onSubmit={handleSubmit(onSubmit)} noValidate>
{/* Honeypot */}
<div style={{ display: 'none' }} aria-hidden>
<input {...register('website')} tabIndex={-1} autoComplete="off" />
</div>
<div>
<label htmlFor="name">Имя *</label>
<input id="name" {...register('name')} aria-describedby={errors.name ? 'name-error' : undefined} />
{errors.name && <p id="name-error" role="alert">{errors.name.message}</p>}
</div>
<div>
<label htmlFor="email">Email *</label>
<input id="email" type="email" {...register('email')} />
{errors.email && <p role="alert">{errors.email.message}</p>}
</div>
<div>
<label htmlFor="message">Сообщение *</label>
<textarea id="message" rows={5} {...register('message')} />
{errors.message && <p role="alert">{errors.message.message}</p>}
</div>
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? 'Отправка...' : 'Отправить'}
</button>
</form>
);
}
Срок реализации
Контактная форма с валидацией, honeypot, email-уведомлением и автоответом для Laravel + React: 1–2 дня. С сохранением в БД и панелью управления обращениями: 2–3 дня.







