W Symfony wiadomość e-mail można wysłać standardowo w PHP, aczkolwiek lepiej wykorzystać w tym celu gotową bibliotekę Swift Mailer z szeregiem udogodnień, które nam oferuje. Oprócz własnego serwera pocztowego można używać poczty popularnych dostawców jak np: Mandrill, SendGrid oraz Amazon SES.
W tym poście ugryziemy tak naprawdę dwa tematy:
1. Budowa formularzy w Symfony 4 na przykładzie formularza kontaktowego.
2. Wysyłanie wiadomości e-mail za pomocą usługi Swift Mailer.
A więc zaczynamy 😉 !
INSTALACJA
Aby korzystać z Swift Mailer musimy pobrać i zainstalować pakiet SwiftmailerBundle. W tym celu uruchom w wierszu poleceń komendę:
1 |
$ composer require symfony/swiftmailer-bundle |
KONFIGURACJA
W pliku swiftmailer.yaml (/config/packages/swiftmailer.yaml) można ustawić różne konfiguracje dla poczty. Dla celów testowych użyjemy tylko podstawowych atrybutów:
1 2 3 |
swiftmailer: url: '%env(MAILER_URL)%' spool: { type: 'memory' } |
- spool – kolejkowanie wiadomości e-mail; typ memory – czyli z bufora pamięci (domyślnie jest z pliku – file)
Więcej ustawień znajdziesz tutaj.
W pliku .env wprowadzamy zmienną środowiskową MAILER_URL z parametrami naszego konta pocztowego (host, port, username, password etc.):
1 |
MAILER_URL=gmail://testxyz@gmail.com:password@localhost |
W tym przykładzie, jak widać używam poczty Gmail. Oczywiście nic nie stoi na przeszkodzie, aby skorzystać z innego konta. Szczegóły znajdziesz w dokumentacji.
FORMULARZ KONTAKTOWY
Aby zbudować prosty formularz skorzystamy z najlepszych praktyk Symfony stosowanych w tej dziedzinie 🙂 W tym celu stwórz klasę np: Contact (/src/Entity/Contact.php) i zdefiniuj pola formularza, np: e-mail i wiadomość:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?php // src/Entity/Contact.php namespace App\Entity; use Symfony\Component\Validator\Constraints as Assert; class Contact { /** * @Assert\NotBlank() */ public $email; /** * @Assert\NotBlank() */ public $content; } |
Następnie utwórz plik ContactType.php (/src/Form/ContactType.php). W klasie dodajemy pola (add), które zostaną załączone w kontrolerze i wyrenderowane na stronie, w kolejności podanej w metodzie buildForm. Taki sposób pozwala na wielokrotne wykorzystanie kodu formularza w różnych miejscach i swobodę w jego modyfikacji.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<?php //src/Form/ContactType.php namespace App\Form; use App\Entity\Contact; // dołączamy klasę Contact use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; // dołączamy klasy kontrolek typu: textarea, email, submit use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\Extension\Core\Type\EmailType; use Symfony\Component\Form\Extension\Core\Type\SubmitType; class ContactType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('email', EmailType::class) ->add('content', TextareaType::class) ->add('save', SubmitType::class, ['label' => 'Wyślij formularz']) ; } public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ 'data_class' => Contact::class, ]); } } |
Kontroler ContactController.php (/src/Controller/ContactController.php) jest odpowiedzialny za wyrenderowanie formularza i wysłanie wiadomości po naciśnięciu przycisku submit. Przeanalizuj zawartość poniższego pliku. W poszczególne linie kodu wplotłem komentarze wyjaśniające.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
<?php // src/Controller/ContactController.php namespace App\Controller; // dołączamy nasze klasy Contact i ContactType use App\Entity\Contact; use App\Form\ContactType; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\HttpFoundation\Request; class ContactController extends AbstractController { /** * @Route("/contact", name="contact") */ public function contact(Request $request, \Swift_Mailer $mailer) { $contact = new Contact(); // tworzymy obiekt formularza $form = $this->createForm(ContactType::class, $contact); // dołączamy pola formularza $msg = null; // ustawiamy domyślny komunikat (pusty) if ($request->isMethod('POST')) // jeżeli wywołano globalną metodę POST { $form->submit($request->request->get($form->getName())); // sprawdzamy czy naciśnięto przycisk i czy formularz jest poprawny if ($form->isSubmitted() && $form->isValid()) { $msg = 'Wiadomość została wysłana.'; // ustawiamy komunikat // tworzymy obiekt Swift_Message z parametrami wiadomości... $message = (new \Swift_Message('Formularz kontaktowy')) ->setFrom($form->get('email')->getData()) ->setTo('testxyz@gmail.com') ->setBody($this->renderView('send.html.twig',array( 'email' => $form->get('email')->getData(), 'content' => $form->get('content')->getData() )),'text/html'); $mailer->send($message); // wysyłamy formularz } else { $msg = 'Error:'; // jeśli coś poszło nie tak, wyświetli się komunikat z błędem } } // renderujemy podstronę z formularzem // w tablicy przekazujemy obiekt formularza - form oraz komunikat - message return $this->render('contact.html.twig', ['form' => $form->createView(), 'message' => $msg]); } } |
Dodatkowe objaśnienia:
- Swift_Message(’Formularz kontaktowy’) – w nawiasie podajemy tytuł wiadomości
- setFrom – od kogo jest wiadomość – pobieramy ze zmiennej globalnej $form->get(’email’)->getData()
- setTo – adresat wiadomości, np: setTo(’testxyz@gmail.com’)
- setBody – zawartość wiadomości. W pierwszym parametrze dołączamy szablon wiadomości $this->renderView(’send.html.twig’ (patrz-> poniżej zawartość pliku). W drugim parametrze przekazujemy tablicę zmiennych, które chcemy przekazać w szablonie np: email, content. Jako trzeci parametr podajemy format danych wiadomości e-mail, czyli: text/html.
Zawartość szablonu wiadomości: send.html.twig (/templates/send.html.twig):
1 2 3 |
<p><strong>E-mail</strong>: {{ email }}</p> <p><strong>Treść wiadomości</strong>:</p> {{ content }} |
Zawartość formularza na stronie: contact.html.twig (/templates/contact.html.twig):
1 2 3 4 5 6 7 |
<h1>Formularz kontaktowy</h1> {{ form_start(form) }} {{ form_widget(form) }} {{ form_end(form) }} {{ message }} |
Formularz jest generowany automatycznie $form->createView() na podstawie klas Contact i ContactType. Dla przypomnienia fragment z kontrolera:
1 2 3 4 |
$contact = new Contact(); $form = $this->createForm(ContactType::class, $contact); // ... return $this->render('contact.html.twig', ['form' => $form->createView(), 'message' => $msg]); |
Zmienna message wyrzuca komunikaty o błędach, etc.
Wejdź na stronę: //example.com/public/index.php/contact/ i sprawdź działanie formularza.
I to wszystko 🙂
Do następnego! ->