Тридцатый седьмой урок. Обработка форм с помощью PHP

Любая форма отправляется на адрес, указанный в атрибуте action. Обычно это php-обработчик, в задачу которого входит приём данных, их проверка на валидность, выполнение какого-то действия (например отправка сообщения на email) и выдача в браузер результата операции.

Программирование выполняется на PHP — это язык, который работает на стороне сервера. Как вы помните, JavaScript — это язык который работает в браузере каждого посетителя. А PHP работает на самом сервере.

Сервер (Apache) смотрит расширение файла и если оно .php, то подключается модуль PHP, который собственно и выполняет код файла. Если при этом выводится какой-то текст (например html-код), то сервер отдаёт его в браузер.

Синтаксис PHP достаточно простой и интуитивно понятный. Следует понимать, что php-код выполняется только если он размечен с помощью <?php php-код ?>. Такой подход позволяет комбинировать html и php-код в одном файле.

<?php
	$header = 'Заголовок'; 
?>

<h1><?php echo $header; ?></h1>

В данном примере мы задали переменную $header и ниже вывели её с помощью php-функцими echo. В PHP все переменные начинаются с символа $. Имя переменной регистрозависимо.

Команда echo (и похожая на неё print) выводит текст в браузер. В некоторых случаях можно использовать сокращение этой конструкции:

<?php
	$header = 'Заголовок'; 
?>

<h1><?= $header ?></h1>

То есть <?= что выводить ?> позволяет немного сократить код и сделать его более читабельным.

Если php-код завершает файл, то закрывающий ?> можно не указывать. Более того, его даже не рекомендуется указывать в целях безопасности. Поэтому часто в php-файлах в конце нет этого закрывающего php-тэга.

В PHP очень много разных функций. Часть из них являются языковыми конструкциями (как echo). Часть функций входит в стандартные модули, которые всегда (как правило) подключаются. Часть функций доступны, только когда подключены их библиотеки на сервере. Кроме того, некоторые функции могут быть доступны только в новых версиях PHP, или наоборот, быть исключенными.

PHP достаточно активно развивается (особенно в последние годы), поэтому новые версии языка появляются довольно часто. Например сейчас текущая версия PHP 7.2. Однако, поскольку PHP — серверный язык, то он должен быть установлен и обновлен на самом сервере. Сложность в том, что версия PHP будет единой для всего сервера, а значит все клиенты хостинга будут работать с одной версией. И если, скажем, установить последнюю, то для многих сайтов это создаст проблемы совместимости — они просто перестанут нормально работать.

На хостингах стараются решить эту проблему по разному, обычно предлагая клиентам переключение php-версий в пределах своего аккаунта. Но в любом случае, из-за серьезных различий, следует использовать ту версию, которая наиболее распространена. На текущий момент оптимальный вариант — это PHP 7.0 (не выше), который хорошо совместим до версии 5.5. Если php-код старый, то лучше использовать версию 5.3. Если же код и здесь не поддерживается, то он очень старый и тогда следует использовать PHP 5.2. Версии 6.0 не существует, а версии 5.4 и 5.6 были «переходными».

В настройках Open Server есть закладка, где можно выбрать нужный модуль PHP.

Самый проблемный вариант это 7.1 и выше, поскольку команда PHP удалила ряд важных функций, которые часто использовались раньше. Изучать, естественно, лучше сразу 7-ю версию, но всегда следует учитывать тот факт, что новый код может не работать на серверах, использующих старые версии PHP. Как я отметил сегодня граница проходит по версии 5.3, который работает на большинстве хостингах. В будущем, если вы будете заниматься программированием, всегда проверяйте работу php-кода на версии 5.3 или хотя бы 5.5.

Но всё это нюансы. Основа PHP стабильна, а для наших задач годится любая версия. :-)

Вернёмся к формам.

Браузер, отправляя форму, формирует т.н. POST-запрос к серверу. Мы рассматривали get и post метод отправки формы. Именно этот метод и влияет на то, как будет работать обработчик php.

Для практического рассмотрения сделаем простую форму из нескольких полей. Метод будет post, а в качестве action укажем отдельный php-файл (my-post.php) на сервере.

<form class="w100 pad20 bor1 bor-solid bor-gray300" action="ВАШ САЙТ/my-post.php" method="post">
	<p><input type="text" class="w100" placeholder="name" name="name"></p>
	<p><input type="text" class="w100" placeholder="phone" name="phone"></p>
	<p><textarea class="w100" placeholder="message" name="message"></textarea></p>
	<p><label><input type="checkbox" name="rules"> I agree with the rules</label></p>
	<button type="submit" class="i-check">Send</button>
</form>

Файл my-post.php будет такого содержания:

<?php

echo 'Это my-post.php';


# end of file

Hазместите его по указанному адресу так, чтобы он был доступен через браузер. Вы должны увидеть сообщение «Это my-post.php».

Теперь, если нажать кнопку Send, браузер отправит форму на указанный адрес и мы увидим соответствующее сообщение.

Сама форма была передана через post-запрос, который PHP автоматически отслеживает и результат помещает в специальную переменную $_POST. Это структура данных в виде массива. Чтобы её увидеть мы воспользуемся функцией print_r() — она специально создана для вывода сложных структур.

Изменим php-файл (ниже в примерах я буду указывать только php-код без обрамляющих <?php):

print_r($_POST);

Еще раз отправьте форму и в браузере нажмите просмотр исходного html-кода странцы. Мы увидим массив $_POST вот в таком виде.

Array
(
    [name] => Вася
    [phone] => 09
    [message] => Привет!
    [rules] => on
)

То есть каждый элемент массива содержит название поля (атрибут name) и его введенное значение посетителем.

Обратите внимание как передался чекбокс (rules). Если его не отмечать, то массив изменится:

Array
(
    [name] => Вася
    [phone] => 09
    [message] => Привет!
)

То есть чекбокс передается только если он отмечен. На этот момент я раньше обращал внимание. С точки зрения php-программиста, нет никакой разницы какой именно использовался элемент формы (текстовый input или textarea или специальный input). На входе только именованный массив. Чтобы обеспечить гарантированную передачу чекбокса, следует явно задать его значение (value) и добавить перед ним скрытый input с дефолтным значением value и тем же именем name.

...
	<input type="hidden" name="rules" value="0">
	<p><label><input type="checkbox" name="rules" value="1"> I agree with the rules</label></p>
...

Теперь при отправке формы, в $_POST всегда будет элемент массива rules со значением 1, если чекбокс отмечен, и 0 — если не отмечен. Используйте этот приём при верстке форм с чекбоксами.

Array
(
    [name] => Вася
    [phone] => 09
    [message] => Привет!
    [rules] => 1
)

После получения формы php-скрипт должен что-то с ним сделать. Пока мы опустим эту часть, а просто выведем сообщение, что страница отправлена и сделаем редирект на какой-нибудь сайт (в этом примере на гугл).

header("refresh:3;url=https://google.com/"); 

echo '<p>Спасибо, ваше сообщение отправлено!</p>';

Функция header отправляет браузеру http-заголовок, в нашем случае это переход через 3 секунды на указанный адрес (подставьте свой вариант). При отправке http-заголовков следует учитывать тот момент, что они должны отправляться до любого вывода в браузер. Именно поэтому headerрасполагается перед echo. Если разместить ниже, то PHP выдаст ошибку.

Перед тем, как что-то программировать, следует продумать алгоритм программы. Вообще любое программирование, это в первую очередь создание агоритма, и в последнюю — его практическая реализация. И это не зависит от языка, будь то PHP, JS, Delphi, C++ или Бэйсик. Вначале алгоритм, после программирование.

Давайте подумаем какой должен быть алгоритм нашего php-скрипта. Получив данные, нужно их проверить, чтобы не было пустых полей, особенно номер телефона. Если все нормально, то нужно отправить email на наш адрес с этими данным. Если на каком-то этапе произошла ошибка, то нужно вывести уведомление в браузер, чтобы посетитель знал о проблеме.

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

Написание алгоритма возможно в любом варианте, главное, чтобы он был понятен (как пример: РАЯ). Покажу вам простой пример с использованием условий и блоков (фигурные скобки обозначают единый блок).

ЕСЛИ (есть post-данные)
{
	$error = '';  // сообщение об ошибке изначально пустое
	
	ЕСЛИ ЕСТЬ поле name 
		$name = поле name.	
	ИНАЧЕ
		$error += 'Не указано имя'
	
	ЕСЛИ ЕСТЬ поле phone 
		$phone = поле phone.	
	ИНАЧЕ
		$error += 'Не указан телефон' // добавляем сообщение об ошибке
	
	ЕСЛИ ЕСТЬ поле message 
		$message = поле message.	
	ИНАЧЕ
		$message = '' // нет текста сообщения = пусто 
	
	ЕСЛИ поле rules = 0 
		$error += 'Нужно согласиться с правилами'
	
	ЕСЛИ $error содержит текст
	{
		ВЫВОД $error
		
		РЕДИРЕКТ НА УКАЗАННЫЙ АДРЕС (с формой)
	}
	ИНАЧЕ
	{
		// все нормально
		
		формируем поля для отправки письма на основе $name, $phone и $message
		
		EMAIL // отправляем письмо
		
		ВЫВОД 'Спасибо, ваше сообщение отправлено!'
		
		РЕДИРЕКТ НА УКАЗАННЫЙ АДРЕС (например главная страница)
	}
}
ИНАЧЕ
{
	ВЫВОД 'Ошибочные данные'
}

Хорошая новость в том, что в обязанности верстальщика не входит написание php-кода, во всяком случае с нуля. Именно поэтому вы будете использовать какие-то готовые наработки для своих сайтов. Но верстальщик всё-равно должен неплохо ориентироваться в php-коде хотя бы на уровне хорошего понимания синтаксиса и базовых основ программирования.

Для изучения PHP вы можете скачать справочник языка в формате chm (windows-справка) или воспользоваться online-версией Руководства по PHP. Как бы там ни было, изучение PHP в наш курс не входит, потому я сразу приведу готовое решение для отправки формы.

Следует отметить, что мы рассматриваем простой вариант отправки, но существует ещё один — без перезагрузки страницы с использованием технологии AJAX. Она сложна не только для новичков, но и для более опытных вебмастеров, к том уже требует не только программирования PHP, но и JavaScript (jQuery). См. Отправка произвольной формы без перезагрузки страницы.

Поскольку наша страница работает на LPF, то мы будем использовать его возможности.

Форма отправки будет точно такой же, только атрибут action должен быть пустым или можно его удалить. То есть страница будет отправлять post-запрос на саму себя. Поля имени и телефона отмечены как обязательные (required).

<form class="w100 pad20 bor1 bor-solid bor-gray300" method="post">
	<p><input type="text" class="w100" placeholder="name" name="name" required></p>
	<p><input type="text" class="w100" placeholder="phone" name="phone" required></p>
	<p><textarea class="w100" placeholder="message" name="message"></textarea></p>
	<p><label><input type="checkbox" name="rules"> I agree with the rules</label></p>
	<button type="submit" class="i-check">Send</button>
</form>

В LPF предусмотрен «перехват» post-запросов. В каталоге страницы разместите файл _post.php, который и будет срабатывать при получении непустых POST-данных.

В этом файле мы разместим обработчик данных, а также отправку сообщения на ваш email. В случае удачной отправки мы сделаем редирект на страницу сайта «сайт/ok». Её необходимо заранее создать. В случае ошибки, выведем сообщение и сделаем переход на исходную страницу с формой.

В php-скрипте в переменных нужно будет указать свои данные: адрес email, тема сообщения. Там же можно будет задать другие адреса для редиректов.

Сохраните файл _post.txt как _post.php в каталоге страницы. В переменных разместите свои данные и можете проверить работу отправки формы.

В переменной $from укажите email-адрес своего сервера (можно вымышленного, но этого же домена). Если этого не сделать, то почтовые сервисы примут письмо за спам и могут его заблокировать.

Если вы проверяете работу на Open Server, то реальной отправки письма не будет (поскольку нет почтового сервера), но само письмо сохранится в виде текстового файла в каталоге OpenServer\userdata\temp\email\, где вы сможете его найти и прочитать.

Задание

Задания доступны только после авторизации.