Laravel AJAX: делаем форму обратной связи

Опубликовано: 01.09.2018

видео Laravel AJAX: делаем форму обратной связи

Верстка сайта с нуля по макету - Форма обратной связи

Доброго времени суток!



Сегодняшняя статья является продолжением цикла публикаций, посвящённых созданию сайта на Laravel , в рамках которого мы подробно рассмотрим процесс разработки корпоративного многостраничного сайта на базе шаблона с контактной формой и возможностью ведения блога.

Т.е. то, чем занимаются большинство веб-студий, требуя за свои услуги от 1000$. Если же вы наберётесь терпения изучить весь курс, то сэкономите означенную сумму и время на объяснение деталей сторонним исполнителям


Часть 2. Форма обратной связи для сайта: Ajax - отправка без перезагрузки

Поэтому не забываем подписываться на обновления проекта, чтобы быть в курсе новых статей.

Итак, напомню, что в одной из предыдущих статей мы рассмотрели создание правил роутинга и контроллеров Laravel для каждой отдельной страницы сайта, в которых будем размещать код для вывода данных на страницах в дальнейшем.


PHP - Верификация email через почту

Сегодня же мы используем полученный опыт и приступим к созданию формы обратной связи, на примере которой я покажу вам, как реализовать популярную технологию AJAX в рамках Laravel framework.

Забегая наперёд, скажу, что саму отправку email через форму мы сегодня делать не будем, т.к. для обзора способов отправки email в Laravel запланирована отдельная публикация, а всего лишь подготовим всё необходимое для этого.

Итак, чем же мы сегодня конкретно займёмся?

Сказав, что сегодня мы будем делать обратную форму на Laravel, я немного слукавил, т.к. она у нас уже есть и доступна по url — laravel.portfolio/contact (я решил его немного поменять, поэтому в дальнейшем форма будет доступна по url laravel.portfolio/contacts).

Единственное, чего ей сейчас не хватает — это функциональности, т.е. непосредственно отправка письма не работает и при нажатии на кнопку «Отправить» фреймворк нам выдаёт ошибку.

Что же тогда мы будет творить, если самой отправкой письма заниматься будем в следующей статье?

Суть нашей сегодняшней работы будет заключаться в написании функции, которая будет вызываться при нажатии на кнопку «Отправить» и будет оправлять данные, введённые пользователем в поля формы, на сервер, а затем, при получении ответа с сервера будет выдавать уведомление об успешной или неуспешной отправке сообщения.

И ещё один нюанс — всё это будет происходить без перезагрузки страницы, т.е. с использованием технологии AJAX.

Можно было, конечно, обойтись и без этого, просто перезагружая страницу, но это слишком просто, скучно и несовременно.

К тому же, AJAX нам понадобится в дальнейшем при работе с Laravel, а при его реализации часто случаются неприятные сюрпризы (у меня их тоже было полно, когда я только начинал работать с этим фреймворком), поэтому я и решил рассмотреть все «подводные камни» сейчас, чтобы не отвлекаться на них потом.

О них мы сейчас и поговорим.

Особенности реализации AJAX в Laravel

AJAX-запросы, по сути, ничем не отличаются от обычных HTTP-запросов к серверу, т.е. они могут отправляться теми же методами (GET, POST, PUT, DELETE и т.д.) с теми же самыми заголовками (HEADERS).

Исторически сложилось, что самыми популярными методами передачи запросов являются GET и POST. В GET-запросах параметры передаются через URL, а при POST они доступны только из суперглобальных массивов $_POST или $_REQUEST.

По этим же причинам метод POST считается более безопасным для передачи конфиденциальных данных, т.к. параметры GET-запроса и их значения можно легко увидеть в браузере.

Исходя из этих соображений, при отправке email в Laravel с помощью AJAX мы будем пользоваться POST-запросом. И тут нас ждёт один неприятный сюрприз, т.к. по умолчанию все AJAX-запросы, отправляемые POST-методом, будут приводить к ошибке:

Что за чушь? Что ещё за VerifyCsrfToken.php, если мы к данному файлу непосредственно не обращаемся?

Если у вас возникли подобные вопросы, то ответы ждут вас в статье о Laravel CSRF .

После её прочтения вы сами поймёте, что нужно сделать, чтобы AJAX POST запрос в Laravel заработал. Если же вопрос всё равно останется открытым, то ответ на него вы получите далее.

Итак, нам нужно будет сделать следующее:

Подготовить HTML-форму для AJAX-отправки запроса Реализовать JavaScript-код для отправки и обработки результатов запроса Прописать правило роутинга Laravel Метод контроллера Laravel для совершения действий на сервере (в будущем именно там у нас будет размещаться код отправки email)

Ну, что такое AJAX и в чём заключается его суть, я думаю, нет смысла описывать, т.к. технология уже лет 10 как не инновационная Если вдруг вам нужны будут подробности — напишите об этом в комментариях.

Поехали

Итак, что же конкретно мы будем делать?

На данный момент на сайте у нас уже есть контактная форма, которая отправляет POST-запрос на сервер скрипту contact.php. Загляните в файл с кодом контактной формы /resources/views/contact.blade.php, где это прописано:

<form id="contactform" action="contact/contact.php" method="post" class="validateform" name="send-contact"> ... </form>

Кстати, немного подумав, решил переименовать данный файл и соответствующую ссылку на страницу с контактной формой, так что в дальнейшем файл будет называться contacts.blade.php, чтобы было созвучно с новым url /contacts.

Как видите, в шаблоне, который мы используем для создания сайта, всё уже сделано до нас — и скрипт отправки письма, и валидация данных формы (проверка корректности ввода). Но мы от этого избавимся и изобретём собственный велосипед, чтобы было понятно, как он устроен

Кроме того, данные фичи есть не во всех щаблонах, поэтому нужно уметь реализовывать подобное самостоятельно.

Поэтому очищаем тэг формы от ненужных атрибутов. И, чтобы избавится от валидации данных формы, встроенной в шаблон, очистим поля формы от ненужных атрибутов. Стандартной Bootstrap валидации нам вполне хватит.

Ну, и для добавления реализации Laravel CSRF protection и для исключения ошибки проверки CSRF token, о которой мы говорили ранее, в нашу форму следует добавить следующее:

{{ csrf_field() }}

Или воспользоваться другими вариантами указания токена, которые были перечислены в статье о Laravel CSRF по ссылке выше.

В итоге наша форма примет следующий вид:

<form id="contactform" method="POST" class="validateform"> {{ csrf_field() }} <div id="sendmessage"> Ваше сообщение отправлено! </div> <div id="senderror"> При отправке сообщения произошла ошибка. Продублируйте его, пожалуйста, на почту администратора <span>{{ env('MAIL_ADMIN_EMAIL') }}</span> </div> <div class="row"> <div class="col-lg-4 field"> <input type="text" name="name" placeholder="* Введите ваше имя" required /> </div> <div class="col-lg-4 field"> <input type="email" name="email" placeholder="* Введите ваш email" required /> </div> <div class="col-lg-4 field"> <input type="text" name="subject" placeholder="* Введите тему сообщения" required /> </div> <div class="col-lg-12 margintop10 field"> <textarea rows="12" name="message" class="input-block-level" placeholder="* Ваше сообщение..." required></textarea> <p> <button class="btn btn-theme margintop10 pull-left" type="submit">Отправить</button> <span class="pull-right margintop20">* Заполните, пожалуйста, все обязательные поля!</span> </p> </div> </div> </form>

Как видите, я ещё решил добавить блок с сообщением о неудачной отправке (такое тоже случается) с просьбой связаться с администратором по email напрямую. Email администратора я записал в файл окружения .env, который лежит в корне проекта, в следующем виде:

[email protected]

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

Ну, а для вывода переменных окружения в blade я воспользовался следующей конструкцией:

{{ env('MAIL_ADMIN_EMAIL') }}

Как видите, я воспользовался функцией-хэлпером Laravel env(), которая в качестве аргумента принимает имя переменной окружения, а возвращает, следовательно, её значение. Вызывать её можно как в файлах шаблонизатора, так и из php-кода контроллеров и моделей.

Более подробно о ней вы можете прочитать здесь — https://laravel.com/docs/5.4/helpers#method-env. И вообще рекомендую распечатать данную статью документации Laravel и повесить себе на стеночку, т.к. Laravel helpers — вещь очень удобная и позволяет иногда сэкономить время на написании велосипедов.

Ну, и для визуального оформления сообщения об ошибке отправки письма с контактной формы я добавил стили для селектора #senderror в файлик /public/css/style.css следующим образом:

#sendmessage, #senderror { border:1px solid #e6e6e6; background:#f6f6f6; display:none; text-align:center; padding:15px 12px 15px 65px; margin:10px 0; font-weight:600; margin-bottom:30px; } #senderror { color: #f00; } #senderror span { font-weight: bold; }

Только не нужно бездумно копипастить код. Первый блок свойств уже существует для селектора #sendmessage. Всё, что нужно, — это добавить эти свойства для #senderror, прописав его через запятую. Остальные два блока просто копируем.

Итак, на этом HTML часть контактной формы готова. Следующим этапом мы подготовим JS-код для передачи запроса и обработки его результатов без перезагрузки страницы.

Поскольку AJAX — это JavaScript технология, то вся магия, как раз и будет происходить здесь. Под магией подразумевается отправка запроса и реакция при получении ответа от сервера.

В проекте мы пользуемся JavaScript библиотекой jQuery (многие называют её JS-фреймворком, кому как угодно), поэтому и код AJAX запроса будет с использованием jQuery конструкций. Сам же код будет следующим:

$(document).ready(function(){ $('#contactform').on('submit', function(e){ e.preventDefault(); $.ajax({ type: 'POST', url: '/sendmail', data: $('#contactform').serialize(), success: function(result){ console.log(result); } }); }); });

Пару слов о том, что же здесь написано. Функция отправки AJAX запроса будет работать только когда страница загрузится, о чём говорит первая строка кода.

Запрос мы будем отправлять при событии submit HTML формы, т.е. при её подтверждении, что видно на второй строчке кода.

На третьей строке происходит прерывание стандартного подтверждения отправки формы. Если его не прервать, то вместо нашего кода Laravel пытался бы отправить запрос на action формы, которого нет, и мы получали бы ошибку о несуществующем URL.

На пятой строке можно увидеть вызов специальной функции jQuery ajax, которая делает отправку и обработку AJAX запросов невероятно удобной и простой, лишая разработчиков необходимости вникать в премудрости отправки и обработки результатов XMLHttpRequest из чистого JavaScript-кода.

Шестая, седьмая и восьмая строки говорят о том, что запрос будет отправляться методом POST на URL /sendmail и в теле запроса в качестве параметров будут передаваться данные, введённые пользователем в поля HTML формы.

Дальнейший код описывает действие, которое должно произойти при получении ответа от сервера. Пока что я решил прописать только вывод текста ответа в консоль браузера. В дальнейшем же, когда отправка email будет реализована, мы заменим данную «заглушку» на что-то более осмысленное.

В завершение описания данного этапа скажу, что код выше необходимо вставить в самый конец нашего кастомного JS-файла /public/js/app.js.  И неплохо будет почистить кэш браузера, иначе мы рискуем не увидеть результат выполнения.

Laravel AJAX — прописываем роуты

Итак, как вы могли заметить, в JS функции отправки AJAX запроса мы указали тип запроса и URL, на который он будет передан. Теперь самое время создать соответствующее правило Laravel routing для того, чтобы указать фреймворку как нужно обрабатывать данный запрос.

Для этого заходим в файл /routes/web.php и прописываем в его конце следующее правило:

Route::post('/sendmail', 'Ajax\[email protected]');

Данный код говорит фреймворку, что при поступлении POST запроса на URL /sendmail следует вызвать метод контроллера Ajax\ContactController send().

Обработка Laravel AJAX запроса

Несмотря на то, что у нас уже есть контроллер ContactController, я решил для обработки AJAX запросов создать отдельный каталог с одноименным названием и заполнить его специальными одноимёнными контроллерами для обработки AJAX запросов на страницах сайта, т.к. считаю это архитектурное решение более правильным.

Если вы не разделяете мою точку зрения, можете создать метод send() в файле существующего контроллера /app/Http/Controllers/ContactController.php.

Я же воспользовался для создания нового контроллера уже знакомым алгоритмом.

Запускаем консоль и перемещаемся в каталог сайта:

cd c:/openserver/domains/laravel.portfolio

Выполняем artisan команду для создания нового контроллера:

php artisan make:controller Ajax/ContactController

После успешного выполнения должна была создаться папка /app/Http/Controllers/Ajax с файлом нового контроллера внутри ContactController.php.

Создаём в нём новый метод send(), который в качестве входного параметра будет принимать экземпляр класса Request, у которого в качестве свойств будут доступны тело, заголовок и параметры запроса, обрабатываемого данным методом.

Внутри данного метода в дальнейшем как раз и будет располагаться код отправки email сообщения. Пока же ограничимся «заглушкой», которая будет выводить на экран параметры запроса, которыми в нашем случае являются данные полей HTML формы.

В результате, контроллер Ajax/ContactController будет содержать следующий код:

<?php namespace App\Http\Controllers\Ajax; use Illuminate\Http\Request; use App\Http\Controllers\Controller; class ContactController extends Controller { public function send(Request $request) { dd($request->all()); } }

Проверка выполнения Laravel AJAX запроса

Ну, вот и всё. Все необходимые приготовления выполнены. Осталось только проверить правильность работы нашей реализации Laravel AJAX.

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

Если вы всё сделали правильно, то в консоли должны будут отобразиться введённые в поля формы данные в виде параметров запроса.

Итак, вводим произвольные данные в нашу HTML форму и нажимаем на кнопку «Отправить». В консоли вы должны увидеть следующее:

Если вы увидели данный набор символов — поздравляю, вы всё сделали верно Не обращайте внимание на то, что AJAX ответ от сервера пришёл в таком неприглядном виде, главное — это положительный результат!

Увиденное — это результат выполнения отладочной функции Laravel dd(), которая на самом деле на выходе содержит много HTML кода, скрытого от глаза пользователя. При выводе же HTML кода в консоли браузера он не обрабатывается, и мы на экране видим «голый» HTML и JavaScript.

Если же хотите увидеть Laravel AJAX ответ сервера во всей красе, стоит лишь переместиться на вкладку инструментов разработчика «Network» и нажать на /sendmail, чтобы увидеть следующее:

Как видите, сервер вернул список значений всех полей HTML формы, а также вывел его в консоли, что и было прописано нами в коде.

А это значит, что Laravel успешно выполнил и обработал AJAX запрос, который был нами отправлен через форму обратной связи.

Теперь дело осталось за малым — в контроллере вместо «заглушки» прописать действия, которые будут производиться на сервере при обработке данного запроса, а в JavaScript скрипте прописать сценарии для фронтэнда сайта, выполняемые при успешном получении результатов обработки запроса.

Этим мы и займёмся в следующей статье, где рассмотрим способы отправки email в Laravel более детально. Поэтому подписывайтесь на обновления по ссылке в начале статьи, чтобы получить уведомление на почту о выходе нового материала.

На этом я сегодня с вами прощаюсь и напоминаю, что изменения кода, продемонстрированные в сегодняшней публикации, доступны в репозитории проекта  в коммите под номером 5.

Пишите ваши отзывы в комментариях, предлагайте свои идеи функционала нашего будущего сайта, которые бы вы хотели увидеть и реализовать.

А также вступайте в наши сообщества в социальных сетях, где вы всегда можете побеседовать с единомышленниками и получить ответ на любой оффтопный вопрос.

Пока

rss