FormSubmitController.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. <?php
  2. namespace App\Http\Controllers;
  3. /*
  4. * FormSubmitController — обработка отправки веб-форм с публичного сайта.
  5. * Маршрут: POST /forms/{slug}/submit
  6. * Логика: валидация по конфигурации полей, сохранение Lead, отправка email, JSON-ответ.
  7. */
  8. use App\Mail\LeadNotification;
  9. use App\Models\Lead;
  10. use App\Models\WebForm;
  11. use Illuminate\Http\JsonResponse;
  12. use Illuminate\Http\Request;
  13. use Illuminate\Support\Facades\Mail;
  14. use Illuminate\Validation\ValidationException;
  15. class FormSubmitController extends Controller
  16. {
  17. public function submit(Request $request, string $slug): JsonResponse
  18. {
  19. $form = WebForm::where('slug', $slug)->where('is_active', true)->firstOrFail();
  20. // Строим правила валидации из конфигурации полей формы
  21. $rules = [];
  22. foreach ($form->fields ?? [] as $field) {
  23. if (empty($field['name'])) {
  24. continue;
  25. }
  26. $fieldRules = [];
  27. if (! empty($field['required'])) {
  28. $fieldRules[] = 'required';
  29. } else {
  30. $fieldRules[] = 'nullable';
  31. }
  32. $fieldRules[] = match ($field['type'] ?? 'text') {
  33. 'email' => 'email|max:200',
  34. 'tel' => 'string|max:30',
  35. 'textarea' => 'string|max:3000',
  36. 'checkbox' => 'accepted',
  37. default => 'string|max:500',
  38. };
  39. $rules[$field['name']] = implode('|', $fieldRules);
  40. }
  41. try {
  42. $validated = $request->validate($rules);
  43. } catch (ValidationException $e) {
  44. return response()->json(['errors' => $e->errors()], 422);
  45. }
  46. // Убираем checkbox (согласие) из сохраняемых данных — только факт согласия нужен
  47. $data = collect($validated)
  48. ->filter(fn ($v, $k) => ! $this->isConsentField($form->fields ?? [], $k))
  49. ->toArray();
  50. $lead = Lead::create([
  51. 'form_id' => $form->id,
  52. 'data' => $data,
  53. 'ip' => $request->ip(),
  54. ]);
  55. // Отправляем email уведомление если указан notify_email
  56. if ($form->notify_email) {
  57. try {
  58. Mail::to($form->notify_email)->send(new LeadNotification($lead, $form));
  59. } catch (\Throwable) {
  60. // Не прерываем работу при ошибке email
  61. }
  62. }
  63. return response()->json(['ok' => true]);
  64. }
  65. // Является ли поле чекбоксом-согласием (не нужно хранить в заявке)
  66. private function isConsentField(array $fields, string $name): bool
  67. {
  68. foreach ($fields as $field) {
  69. if (($field['name'] ?? '') === $name && ($field['type'] ?? '') === 'checkbox') {
  70. return true;
  71. }
  72. }
  73. return false;
  74. }
  75. }