Okładka artykułu Tworzymy własny formularz kontaktowy — Z wykorzystaniem PHP
Poradniki

Tworzymy własny formularz kontaktowy

Z wykorzystaniem PHP

Zdjęcie autora Hubert Tulibacki
0

Chyba najczęściej spotykanym elementem stron internetowych jest formularz kontaktowy. Dzięki niemu, użytkownik odwiedzający naszą stronę, może szybko zadać nam nurtujące go pytanie, a być może nawet złożyć zamówienie na produkt, bądź usługę, którą oferujemy. Pokażę wam, jak szybko i łatwo stworzyć własny formularz kontaktowy, który możecie dostosować do własnych potrzeb.

Projekt formularza

Projektując formularz kontaktowy pamiętajcie o jednym: nikt nie lubi ich wypełniać! Tworząc rozbudowany formularz skutecznie zniechęcamy użytkownika do wypełnienia go, a my tracimy szansę na zdobycie potencjalnego klienta. Jedyne pola jakie są nam niezbędne, to: imię i nazwisko – abyśmy wiedzieli, jak zwracać się do wysyłającego, adres e-mail – abyśmy mieli gdzie odpisać oraz treść. W dobie wszechobecnych robotów spamujących będziemy potrzebowali jeszcze pola, które nas przed nimi zabezpieczy. Naszym zabezpieczeniem będzie prosty sprawdzian z tabliczki mnożenia. Roboty z reguły nie mają pojęcia, o co je pytamy i nie będą potrafiły wpisać poprawnej odpowiedzi.

Poniżej więc prosty formularz kontaktowy, który stworzyłem na potrzeby tego artykułu.

<form action="form/send.php" method="post" id="contactform">
    <fieldset>
        <input type="text" name="contact_name" placeholder="Imię i nazwisko" required="required" tabindex="1" />
        <input type="email" name="contact_email" placeholder="Adres e-mail" required="required" tabindex="2" />
        <textarea rows="5" columns="10" name="contact_body" placeholder="Treść wiadomości" required="required" tabindex="3"></textarea>
        <input type="submit" value="Wyślij" tabindex="5" />Podaj wynik: <span class="form_check_1"></span> &times; <span class="form_check_2"></span> = <input type="text" name="contact_check" maxlength="2" tabindex="4" />
        <input type="hidden" name="contact_check_data" value="" />
    </fieldset>
</form>

Do każdego z pól formularza użyłem atrybutu placeholder, który wyświetla tekst podany w nim, gdy pole jest puste. Kiedyś, by osiągnąć ten efekt należało posłużyć się JavaScriptem. Kolejnym atrybutem, na który warto zwrócić uwagę jest required, wymusza on na użytkowniku wpisanie wartości do pola, do którego jest przypisany. Również bardzo przydatna funkcja, która kiedyś była możliwa jedynie za pomocą skryptów. Pole odpowiedzialne za pobieranie adresu e-mail ma typ email, który zmusza użytkownika do podania poprawnego adresu e-mail. Wszystkie wymienione tutaj funkcje to nowość w HTML5.

Ukryty input, a także elementy span służą do wyświetlania działania, którego rozwiązanie jest warunkiem, aby wysłać e-mail. Takie zabezpieczenie antyspamowe jest o niebo lepsze od żmudnego przepisywania liter z obrazków captcha. Cyfry do działania generowane będą przez JavaScript, którego znaczna część botów nie obsługuje, nie zobaczą więc one czynników mnożenia, a nawet jeśli zobaczą, nie będą wiedziały, co z nimi zrobić. Oczywiście jeśli ktoś napisze robota spamującego naszą stronę, to nie unikniemy problemów, ale nie zakładajmy czarnych scenariuszy. Takie zabezpieczenie na stronę z portfolio, albo małą stronę firmową zupełnie wystarczy.

Wysyłamy zapytanie

Mamy już formularz, teraz musimy sprawić, aby zapytanie było wysyłane. Posłużymy się do tego celu technologią AJAX, więc wysłanie formularza nastąpi bez przeładowywania strony. Najpierw jednak, musimy wygenerować cyfry do naszego działania zabezpieczającego. Nie będzie to trudne, wystarczy poniższy kod:

$(function() {
    var check_1 = (Math.floor(Math.random() * 9) + 1).toString(),
        check_2 = (Math.floor(Math.random() * 9) + 1).toString(),
        check = check_1 + check_2;

    $('#contactform span.form_check_1').text(check_1);
    $('#contactform span.form_check_2').text(check_2);
    $('#contactform input[name="contact_check_data"]').val(check);
});

Kod ten wykonujemy, gdy cały dokument będzie gotowy, stąd znajduje się on wewnątrz $(function() {});. Zapis ten będę pomijał w dalszych wycinkach kodu.

Generujemy i zapisujemy do zmiennych dwie liczby z przedziału od 1 do 9, a następnie konwertujemy je do typu string. W trzeciej zmiennej, liczby te łączymy ze sobą (ale nie dodajemy, jakby sugerował zapis – mamy do czynienia ze stringiem, więc połączone liczby 3 i 9 dadzą 39, a nie 12). Następnie osadzamy owe liczby w odpowiednich miejscach w dokumencie. Łączenie tych liczb jest nam niezbędne, ponieważ musimy jakoś potem sprawdzić, jakie liczby były czynnikami mnożenia i jaki powinien być wynik. Do sprawdzania tego dojdziemy za chwilę.

Teraz musimy przypisać zdarzenie do formularza. Kod tej operacji wygląda następująco:

$('#contactform').on('submit', function(e) {
    var $form = $(this),
        $submit = $('input[type="submit"]', $form);

    e.preventDefault();
});

Pierwszą rzeczą jaką robię, to przypisuję elementy, których będę używał, do zmiennych. Jest to formularz oraz przycisk wysyłania. Linijka e.preventDefault(); odpowiada za to, by powstrzymać przeglądarkę od załadowania strony, która znajduje się w atrybucie action – czyli od tego, co domyślnie dzieje się po wciśnięciu przycisku submit. Gdy upewnimy się, że strona nie zostanie przeładowana, możemy przystąpić do wysłania zapytania:

$.post($form.attr('action'), $form.serialize(), function(data) {
    if (data === 'ok') {
        return true;
    }

    return false;
}, 'text');

Do funkcji post przekazaliśmy następujące parametry: zawartość atrybutu action w formularzu, w którym podajemy adres pliku, który będzie przetwarzał zapytanie, zawartość wszystkich pól w formularzu, które pobieramy za pomocą funkcji serialize, funkcję jaka wykona się, gdy zapytanie zostanie zakończone oraz typ danych, jakich się spodziewamy otrzymać z zapytania.

Skupmy się na owej funkcji. Jej zadaniem jest sprawdzenie, czy e-mail z wiadomością został wysłany, czy nie i podjęcie w związku z tym odpowiednich działań. W odpowiedzi oczekujemy dwóch ciągów znaków, albo ok albo nok, które zostaną zapisane do zmiennej data, jako wynik zapytania. Oczywiście plik przetwarzający zapytanie również przygotujemy sami. Ale to za chwilę. Na razie jedyne co musimy o nim wiedzieć to to, że zwraca ok, jeśli e-mail został wysłany oraz nok w przeciwnym wypadku. Ponieważ wcześniej wstępnie sprawdziliśmy poprawność danych, rezultatu negatywnego powinniśmy się spodziewać jedynie, gdy użytkownik źle rozwiąże działanie, albo kiedy wysyłanie maila nie powiedzie się z winy serwera. I z taką ewentualnością musimy się liczyć, więc serwujemy użytkownikowi komunikat, jeśli coś pójdzie nie tak:

$form.prepend('<div class="form-error">Wystąpił błąd podczas wysyłania formularza. Upewnij się, że wypełniłeś wszystkie pola i poprawnie rozwiązałeś działanie.</div>');

Komunikat ten znajdzie się na początku formularza. Przed tym, jak użytkownik spróbuje wysłać poprawiony formularz, musimy tę wiadomość usunąć. Służy do tego poniższy kod:

$('.form-error', $form).remove();

W przypadku, kiedy wysyłanie wiadomości się powiedzie, ukrywamy formularz i wysyłamy użytkownikowi pomyślną wiadomość:

$form.slideUp('fast', function() {
    $form.after('<div class="form-success">Wiadomość została wysłana! Skontaktujemy się z Tobą jak tylko to będzie możliwe.</div>');
});

Kompletny kod powinien wyglądać następująco:

$('#contactform').on('submit', function(e) {
    var $form = $(this), $submit = $('input[type="submit"]', $form);

    e.preventDefault();

    $('.form-error', $form).remove();

    $.post($form.attr('action'), $form.serialize(), function(data) {
        if (data === 'ok') {
            $form.slideUp('fast', function() {
                $form.after('<div class="form-success">Wiadomość została wysłana! Skontaktujemy się z Tobą jak tylko to będzie możliwe.</div>');
            });

            return true;
        }

        $form.prepend('<div class="form-error">Wystąpił błąd podczas wysyłania formularza. Upewnij się, że wypełniłeś wszystkie pola i poprawnie rozwiązałeś działanie.</div>');
        return false;
    }, 'text');
});

Teraz musimy już tylko zadbać o to, aby użytkownik nie próbował wysłać formularza, kiedy wysyłanie ciągle trwa. W tym celu zablokujemy możliwość edycji wszystkich pól formularza, zmienimy etykietę przycisku wysyłania oraz ustawimy zmienną, która będzie informowała o tym, że formularz jest wysyłany. Następnie będziemy ją sprawdzali i przerywali wysyłanie, jeśli jej wartość wyniesie true. Gotowy kod służący do wysyłania formularza znajdziecie poniżej. Zapewne z łatwością znajdziecie tam zmiany, które opisałem w tym akapicie:

$(function() {
    var check_1 = (Math.floor(Math.random() * 9) + 1).toString(),
        check_2 = (Math.floor(Math.random() * 9) + 1).toString(),
        check = check_1 + check_2;

    $('#contactform span.form_check_1').text(check_1);
    $('#contactform span.form_check_2').text(check_2);
    $('#contactform input[name="contact_check_data"]').val(check);

    var sending = false;
    $('#contactform').on('submit', function(e) {
        var $form = $(this), $submit = $('input[type="submit"]', $form);

        e.preventDefault();

        if (sending) {
            return false;
        }

        $('.form-error', $form).remove();

        $('input, textarea', $form).prop('readonly', true);
        $submit.val('Wysyłam…');
        sending = true;

        $.post($form.attr('action'), $form.serialize(), function(data) {
            if (data === 'ok') {
                $form.slideUp('fast', function() {
                    $form.after('<div class="form-success">Wiadomość została wysłana! Skontaktujemy się z Tobą jak tylko to będzie możliwe.</div>');
                });

                return true;
            }

            $form.prepend('<div class="form-error">Wystąpił błąd podczas wysyłania formularza. Upewnij się, że wypełniłeś wszystkie pola i poprawnie rozwiązałeś działanie.</div>');
            $('input, textarea', $form).prop('readonly', false);
            $submit.val('Wyślij wiadomość');
            sending = false;

            return false;
        }, 'text');
    });
});

Przetwarzamy zapytanie

Zostało nam już tylko przetworzyć zapytanie i wysłać wiadomość e-mail. Niestety póki co, wysyłanie maili z poziomu JavaScript nie jest możliwe, będziemy więc musieli posłużyć się skryptem w PHP. Wykorzystamy też klasę PHPMailer, która wykona za nas całą ciężką pracę związaną z porządnym wysyłanie maili z poziomu PHP. Klasę tę do wysyłania maili wykorzystuje między innymi WordPress. Jedyny plik, jaki będzie nam potrzebny nosi nazwę class.phpmailer.php, pobieramy go i umieszczamy w jednym folderze z plikiem send.php, który tworzymy sami. Zajmiemy się teraz uzupełnianiem właśnie tego stworzonego przez nas pliku.

Zaczynamy od załączenia klasy PHPMailer, abyśmy mogli korzystać z jej funkcjonalności, a następnie czyścimy wszystkie wysłane przez użytkownika dane z niepotrzebnych pustych znaków (jak na przykład spacji) na początku i na końcu wpisanych przez niego danych. Ustawiamy też zmienną o nazwie $error i nadajemy jej wartość false, jest to informacja, że jak na razie nie natrafiliśmy na żadne błędy podczas sprawdzania poprawności nadesłanych danych.

require_once 'class.phpmailer.php';

$_POST = array_map('trim', $_POST);

$error = false;

Teraz po kolei sprawdzamy poprawność nadesłanych danych. W przypadku imienia i nazwiska oraz treści wiadomości sprawdzamy jedynie, czy pola te nie są puste. W przypadku adresu e-mail, sprawdzamy dodatkowo, czy podany adres e-mail jest poprawny. Wykorzystujemy do tego metodę ValidateAddress, którą udostępnia klasa PHPMailer. Zostało nam sprawdzenie poprawności obliczeń użytkownika. Wykonujemy więc mnożenie cyfr podanych w polu contact_check_data i porównujemy z tym, co użytkownik wpisał w polu contact_check. Jeśli nasze testy dla któregoś z pól wyjdą niekorzystnie, zmieniamy zawartość zmiennej $error na true.

Zostało już tylko sprawdzić, czy wartość zmiennej $error wynosi true. Jeśli tak, kończymy działanie skryptu, wyświetlając nok.

if (!isset($_POST['contact_name']) || empty($_POST['contact_name'])) {
    $error = true;
}

if (!isset($_POST['contact_email']) || empty($_POST['contact_email']) || !PHPMailer::ValidateAddress($_POST['contact_email'])) {
    $error = true;
}

if (!isset($_POST['contact_body']) || empty($_POST['contact_body'])) {
    $error = true;
}

if (!isset($_POST['contact_check']) || empty($_POST['contact_check']) || (int) $_POST['contact_check'] !== ((int) $_POST['contact_check_data'][0] * (int) $_POST['contact_check_data'][1])) {
    $error = true;
}

if ($error) {
    exit('nok');
}

Jeśli błędów nie ma, możemy przystąpić do wysyłania wiadomości. Tworzymy nową instancję klasy PHPMailer i konfigurujemy ją, ustawiając kolejno kodowanie na UTF-8 (wszystkie pliki, jakie stworzyliśmy również muszą być w tym kodowaniu, nie pisałem tego, bo zakładam, że wszyscy już wiedzą, że w innym kodowaniu stron się już praktycznie nie robi), dodajemy adres i imię nadawcy, adres odbiorcy (czyli ten, na który formularz ma zostać wysłany), przypisujemy temat oraz treść wiadomości. Następnie używając metody Send wysyłamy wiadomość sprawdzając, czy nie było z tym żadnych problemów i wysyłając nok, jeśli były. Jeśli nie było, wysyłamy ok. Mail powinien zostać wysłany, a skrypt, który napisaliśmy wcześniej, powinien otrzymać wiadomość, że wiadomość została wysłana pomyślnie.

Oto cały skrypt PHP gotowy do działania:

<?php

require_once 'class.phpmailer.php';

$_POST = array_map('trim', $_POST);

$error = false;

if (!isset($_POST['contact_name']) || empty($_POST['contact_name'])) {
    $error = true;
}

if (!isset($_POST['contact_email']) || empty($_POST['contact_email']) || !PHPMailer::ValidateAddress($_POST['contact_email'])) {
    $error = true;
}

if (!isset($_POST['contact_body']) || empty($_POST['contact_body'])) {
    $error = true;
}

if (!isset($_POST['contact_check']) || empty($_POST['contact_check']) || (int) $_POST['contact_check'] !== ((int) $_POST['contact_check_data'][0] * (int) $_POST['contact_check_data'][1])) {
    $error = true;
}

if ($error) {
    exit('nok');
}

$mail = new PHPMailer();

$mail->CharSet = 'UTF-8';

$mail->SetFrom($_POST['contact_email'], $_POST['contact_name']);
$mail->AddAddress('example@example.com');
$mail->Subject = 'Wiadomość ze strony internetowej';
$mail->Body = $_POST['contact_body'];

if (!$mail->Send()) {
    exit('nok');
}

exit('ok');

Zakończenie

Mam nadzieję, że implementacja tego skryptu na Waszych stronach nie sprawiła Wam żadnych problemów. Starałem się, aby całość była jak najprostsza i działała bezproblemowo. Skrypt można łatwo dostosować do własnych potrzeb. Wykorzystanie technologii AJAX sprawia, że można go bezproblemowo zaimplementować do istniejących już stron, nawet tych wykonanych jedynie w HTML.

Pobierz Zobacz demo

To może Cię zainteresować