Мой сайт о WordPress и PHP С Днем победы!
23 февраля 2008

Форма обратной связи

Читали 2281 раз
Рубрика: Мои статьи о WordPress, PHP
Навигация: Главная » WordPress » Мои статьи о WordPress

Вначале вам нужно будет посмотреть наш очередной видеовыпуск, оставить комментарий, предложить блог для обзора и уже после узнать, как можно сделать свою форму обратной связи. :)

Создание формы на самом деле совсем несложное занятие. Обычно это входит в учебники по PHP для начинающих. ;) Поэтому особо мудрить не будем, пойдем по стопам классиков.

Алгоритм

Для начала определимся, что для отображения формы и самой отправки мы будем использовать один url/файл. Что-то вроде такого: http://сайт/contact

То есть в action формы мы указываем текущий адрес (точнее вообще ничего не указываем, это заставит браузер отправить данные формы по этому же адресу).

В самом скрипте мы сделаем проверку на полученные данные (POST). Если они есть, то анализируем их и если они корректны (то есть форма была заполнена), то отправляем форму по указанному адресу email. Если же данные были некорректны или их вообще не было, то отображаем форму.

Для WordPress

В WordPress'е это делается с помощью шаблона постоянной страницы. Копируем page.php, прописываем в начале

/*
Template Name: Обратная связь (contact)
*/

Удаляем все, что касается вывода текстов, оставляем только каркас. Через админку создаем постоянную страницу с этим шаблоном.

Не-WordPress

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

Защита от спама

Основная проблема существующих плагинов в том, что они пытаются быть универсальными и содержат слишком много кода. Поэтому помимо проблем с безопасностью самого WordPress, добавляются и проблемы с безопасностью еще и этих плагинов.

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

Код

<?php

	function valid_email($em) {
		if ( eregi("^[a-z0-9._-]+@+[a-z0-9._-]+.+[a-z]{2,3}$", $em) )
			return true;
		else
			return false;
	}

	$form_hide = false; //отобразить форму

	if ($_POST and
		isset($_POST['submit'])
		and
		isset($_POST['contact_name']) // имя
		and
		isset($_POST['contact_mail']) // обратный адрес
		and
		isset($_POST['contact_subject']) // тема письма
		and
		isset($_POST['contact_antispam']) // антиспам
		and
		isset($_POST['antispam1']) // антиспам
		and
		isset($_POST['antispam2']) // антиспам
		)
	{
		// проверяем мыло
		$ok = valid_email($_POST['contact_mail']);

		if ($ok)
		{	// антиспам
			$antispam1s = (int) $_POST['antispam1'];
			$antispam2s = (int) $_POST['antispam2'];
			$antispam3s = (int) $_POST['contact_antispam'];

			if ( ($antispam1s/711 + $antispam2s/931) != $antispam3s )
			{ // неверный код
				$ok = false;
				echo '<h2>Привет роботам! </h2>';
			}
		}

		if ($ok) // все ок, отправляем
		{
			$myemail = 'admin@site.com'; // с какого адреса отправляем
			$email = 'mail@site.com'; // куда приходят письма

			$subject = $_POST['contact_subject'];
			$header = 'From: ' . $myemail;

			$text_email = 'Ваше имя: ' . $_POST['contact_name'] . "\n";
			$text_email .= 'Email: ' . $_POST['contact_mail'] . "\n";
			$text_email .= 'Телефон: ' . $_POST['contact_phone'] . "\n";
			$text_email .= 'Адрес сайта: ' . $_POST['contact_url'] . "\n\n";
			$message = $text_email .= $_POST['contact_message'];

			$text_email = "Вами отправлено сообщение: \n" . $text_email;

			$form_hide = @mail($email, $subject, $text_email, $header);
			if ( isset($_POST['subscribe']) and $_POST['subscribe'])
					@mail($_POST['contact_mail'], $subject, $text_email, $header);

			echo '<h2>Ваше сообщение отправлено!</h2><p>'
					. str_replace("\n", '<br />', htmlspecialchars($subject. "\n" . $message))
					. '</p>';
			$form_hide = true;
		}
		else
		{
			// неверные данные
			echo '<h2>Нужно указать корректные данные</h2>';
		}
	}

	if ( !$form_hide ) : 

		srand((double) microtime() * 1000000);
		$antispam1 = rand(1, 10);
		$antispam2 = rand(1, 10);

?>

<form name="contact-form" class="contact-form" action="" method="post">
	<input type="hidden" name="antispam1" value="<?= $antispam1 * 711; ?>" id="antispam1" />
	<input type="hidden" name="antispam2" value="<?= $antispam2 * 931; ?>" id="antispam2" />

	<table border="0" width="99%" cellspacing="10">
		<tr>
			<td align="right"><label for="contact_name">Ваше имя*</label></td>
			<td><input name="contact_name" type="text" value="" id="contact_name" style="width: 98%;" /></td>
		</tr>
		<tr>
			<td align="right"><label for="contact_mail">E-mail*</label></td>
			<td><input name="contact_mail" type="text" value="" id="contact_mail" style="width: 98%;" /></td>
		</tr>
		<tr>
			<td align="right"><label for="contact_phone">Телефон (с кодом города)</label></td>
			<td><input name="contact_phone" type="text" value="" id="contact_phone" style="width: 98%;" /></td>
		</tr>
		<tr>
			<td align="right"><label for="contact_url">Адрес сайта</label></td>
			<td><input name="contact_url" type="text" value="" id="contact_url" style="width: 98%;" /></td>
		</tr>
		<tr>
			<td align="right"><label for="contact_subject">Выберите тему письма*</label></td>
			<td><select id="contact_subject" name="contact_subject" style="width: 98%;">
					<option>Тема письма1</option>
					<option>Тема письма2</option>
					<option>Тема письма3</option>
					<option>Тема письма4</option>
					<option>Тема письма5</option>
					<option>Тема письма6</option>
					<option>Тема письма7</option>
					<option>Тема письма8</option>
					<option>Тема письма9</option>
				</select></td>
		</tr>
		<tr>
			<td align="right" valign="top"><label for="contact_message">Сообщение:*</label></td>
			<td><textarea name="contact_message" id="contact_message" style="width: 98%; height: 200px;"></textarea></td>
		</tr>
		<tr>
			<td align="right"><label for="contact_antispam">Защита от спама: <?= $antispam1; ?>+<?= $antispam2; ?>=</label></td>
			<td><input name="contact_antispam" type="text" value="" id="contact_antispam" /> Укажите свой ответ</td>
		</tr>
		<tr>
			<td align="right">Отправить копию письма на ваш e-mail?</td>
			<td><input name="subscribe" id="subscribe" value="" type="checkbox" /> Да</td>
		</tr>
		<tr>
			<td align="right"><input name="submit" type="submit" value="отправить" id="submit" /></td>
			<td><input name="clear" type="reset" value="очистить форму" id="clear" /></td>
		</tr>
	</table>
</form>

<?php endif; //if ( !$form_hide )  ?>

Описание

Вначале мы определяем служебную функцию valid_email(), которая возвращает true, если введенный email валидный.

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

Антиспам работает очень просто. После того, как мы сгенерировали два случайных числа, мы выводим их с просьбой указать их сумму. При этом добавляем в форму два скрытых поля, которые содержат эти же самые числа, только умноженные на другие произвольные числа (711 и 931). Вы можете их поменять в самой форме и в коде проверки.

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

Теперь, когда проверка прошла успешно, мы подготавливаем данные для отправки email. Отправка осуществляется стандартной функцией mail(). Обратите только внимание, что если вы тестируете скрипт под Windows, то эта функция скорее всего отключена и реальной отправки письма не будет.

После того, как все отправлено, выводим сообщение, что данные отправленны.

Переменная $form_hide указывает нужно ли отображать саму форму.

Форму я оформил в виде таблицы, но вы можете её переверстать как угодно. Думаю, что сама по себе она не вызовет вопросов. Все очень уж просто.

В коде вам нужно будет указать две переменные

	$myemail = 'admin@site.com'; // с какого адреса отправляем
	$email = 'mail@site.com'; // куда приходят письма

Еще одно замечание для WordPress. Вместо функции mail() можно указать wp_mail(). Обычно это решает проблему с кодировкой.

google.com bobrdobr.ru del.icio.us technorati.com linkstore.ru news2.ru rumarkz.ru memori.ru moemesto.ru

26 комментариев к “Форма обратной связи”

  1. Ryoga:

    Если ещё через smtp передавать письма то ценны форме не будет.

  2. Богдан:

    будем думать что форма хорошая...но у меня хорошее предчувствие:))

  3. Владимир:

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

  4. Игорь Долбин:

    Чего-то я застряю на пункте "Через админку создаем постоянную страницу с этим шаблоном." Не пойму, где же выбирать этот "шаблон"??? При создании новой страницы в правой колонке такого пунктика нет :( .
    Короче я в ужасе :shock: !

  5. elsik:

    у меня не заработало и с @mail() и с @wp_mail()
    почтовые адреса на работу не влияют ?

  6. Максим:

    Вначале файл шаблона сделайте. Тогда он и появится в админке.

  7. SidexQX:

    Хорошая форма, а главное простая! Спасибо! Вот только письмо она отправила мне в utf-8 что огорчило(( Как это исправить?

  8. Artem:

    Большое спасибо!
    Но присоединяюсь к вопросу о кодировке..

  9. Игорь Долбин:

    Форму установил, но вот на мыло приходят крякозябры.
    Мне кажется, всё из-за того, что в WP дефолтно стоит кодировка utf-8...

  10. Максим:

    Для WordPress используйте wp_mail - тогда данные будут отправляться в кодировке блога. Но вообще можно формировать заголовок mail по своему, просто это отдельная тема и отдельные настройки.

  11. elsik:

    да. письма в utf-8 идут. приходится переключать руками письма с макссайта ( попробую еще чтонить из уже готовых модулей

  12. Игорь Долбин:

    Хм, я вроде бы не чайник, но найти ф-цию "mail()" так и не смог :( .

  13. Игорь Долбин:

    А..., всё, нашёл :) . Всё работает.

  14. SidexQX:

    Может кто то прокомментирует как поменять функцию? "mail()" ?

  15. Охотник на зелёных:

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

  16. Mixa:

    А как насчет сделать поля обязательные для заполнения - соответсвенно, надо бы уведомления, когда поля незаполнены выводить...

  17. BaRoN:

    Есть еще такая функция getmxrr. Чтобы е-мейлы вроде bdsuhf74hufsd@dshf743hfurh.com блокировать.

    Код был бы примерно таким:

    $mailparts=explode("@",$em);
    $hostname = $mailparts[1];
    return getmxrr($hostname, $mxrecords);

    В комментах про getmxrr есть и проверка на open relay'ность MX сервера, но 2 лишних соединения на каждый пост коммента, думаю, черезчур. А одно обращение к локальному быстрому DNS серверу не должно слишком напрягать.

  18. Yantar:

    По-моему, в валидный мэйл может входить знак "плюс", который здесь вроде как не учитывается
    Знак плюса очень удобен, потому что гмейл, к примеру, позволяет получать почту как на адрес login@gmail.com, так и на login+keyword@gmail.com - разумеется, все будет сыпаться в один и тот же ящик, но зато фильтры легче настраивать - например, я стараюсь региться на форумах с адресом login+forums@gmail.com, чтобы все сообщения о регистрации сразу приобретали нужную метку. Но увы, валидность такого мейла не всегда учитывается, так что я вынуждена везде оставлять такие комментарии :-)

  19. BaRoN:

    В этом ключе вообще лучше своих регэкспов не писать, а брать чужие :-) Например из той же getmxrr:

    $exp = "^[a-z\'0-9]+([._-][a-z\'0-9]+)*@([a-z0-9]+([._-][a-z0-9]+))+$";
    $b_valid_syntax=eregi($exp, $email);

    Тогда вкупе с проверкой MX получилось бы что-то вроде:
    function valid_email($em) {
    if ( eregi("^^[a-z\'0-9]+([._-][a-z\'0-9]+)*@([a-z0-9]+([._-][a-z0-9]+))+$", $em, $matches) ) {
    return getmxrr($matches[2], $mxrecords);
    }
    else
    return false;
    }

    Код набирал прямо на сайте, не проверял.

  20. Влад:

    А не проще ли поставить плагин обратной связи? :) Хотя как вариант сойдёт. Тем более есть капча ;) :eek:

  21. BaRoN:

    Влад, ну вероятно имеется в виду наличие самописных или просто других CMS - на ВордПрессе свет клином не сошелся... Тем более, что иногда может возникнуть необходимость поправить и саму форму обратной связи

  22. kotovsky:

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

  23. [m.k]:

    >у меня не заработало и с @mail() и с @wp_mail()
    >почтовые адреса на работу не влияют ?
    А по-моему можно использовать простую функцию mail(кому, тема, текст сообщения, заголовки);

  24. Улитка Джус:

    У меня несколько моментов :
    Во первых сообщение отправляется даже если абсолютно все поля пустые и незаполненные, но введен мейл.
    Во вторых нет ограничение на максимальное количество введеных символов, например 1500, а то писать можно письма сколь угодного размера, так никак нельзя.
    И в третьих само сообщение пишется одной длинной строкой, что совершенно неудобочитаемо для того, кто пишет.
    Как все это исправить?

  25. DJ Slava:

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

  26. Dozen:

    Макс ты просто МОЛОДЕЦ!!! Спасибо огромное. :smile:


Оставьте комментарий! (Вы согласны с правилами)

 

:mrgreen: :neutral: :twisted: :arrow: :shock: :smile: :???: :cool: :evil: :grin: :idea: :oops: :razz: :roll: :wink: :cry: :eek: :lol: :mad: :sad: :!: :?:

При добавлении кода (html, php) заменяйте < на &lt; и > на &gt;.
Внимание: антиспам - зверь! Копируйте своё сообщение перед отправкой. На всякий случай.