Benvenuto al Laravel Cafè! Ogni settimana proporremo un nuovo argomento sul mondo Laravel, quindi trova un posto libero, prendi un caffè e condividi le tue opinioni con la comunità! L’idea è di creare un punto di discussione. Se hai qualche perplessità sull’argomento trattato, leggi fino alla fine e fai una domanda usando il forum! Cercheremo di risponderci a vicenda e di aiutarci, ed il confronto ci farà crescere tutti un po’ di più.
Di mercoledì in mercoledì parleremo di qualcosa di diverso, quindi tornaci a trovare! Potresti dare una mano a qualcuno in difficoltà, o ricevere tu un aiuto in caso di problemi! Dai, siediti, il primo caffè lo offriamo noi.
L’Argomento
Nel mondo del web 2.0 l’invio di mail automatizzate è parte integrante della maggioranza delle applicazioni. L’esempio più semplice è la mail di conferma che ci arriva dopo aver effettuato la registrazione ad un portale web, un forum, o a un social network, che viene inviata automaticamente dall’applicativo. Oggi, per la nostra abituale pausa caffè del mercoledì, vediamo come implementare questo servizio su Laravel 5.3.
N.B.: Laravel 5.3 ha diverse novità rispetto ai suoi predecessori e alcune di queste riguardano proprio le API per le mail, ma il codice che vi propongo è tranquillamente adattabile alle versioni antecedenti con un controller apposito.
Il Codice
Tralascerò la parte di configurazione del servizio (e vi rimando direttamente alla documentazione ufficiale) dato che può variare a seconda delle necessità del developer. Come di consueto vi propongo prima di tutto la struttura del filesystem:
app/
|-- Http/Controllers
|-- MailController.php <-- Controller per l'invio delle mail
|-- Mail/ <-- Cartella base dei modelli "mailable" https://laravel.com/docs/5.3/mail#generating-mailables
|-- Contact.php <-- Classe che si occupa del build della mail di richiesta informazioni
resources/views/ <-- Cartella viste
|-- emails <-- Cartella omissibile
|-- contact.blade.php <-- View che fa da template per mail richiesta informazioni
Utilizzando il comando php artisan make:mail Contact
Laravel ci aiuta ad automatizzare la creazione della classe che rappresenta in modo astratto quanto l’utente fanale riceverà nella propria casella di posta. A mio avviso se automatizzasse anche la creazione della vista base non sarebbe male, ma potrebbe essere uno spunto per qualche plugin o una futura feature di Laravel.
Dopo aver lanciato il comando precedentemente descritto, il risultato sarà la creazione di un’estensione della classe IlluminateMailMailable
e contenente il metodo build()
che ci permette di impostare sia tutte le informazioni riguardanti mittenti e destinatari, la vista da utilizzare come template ed eventualmente implementare anche code di invio.
Contact.php
namespace AppMail;
use IlluminateBusQueueable;
use IlluminateMailMailable;
use IlluminateQueueSerializesModels;
use IlluminateContractsQueueShouldQueue;
class Contact extends Mailable
{
use Queueable,
SerializesModels;
/**
* Array with sender informations.
* [ 'name' => 'John', 'mail' => 'john@doe.com' ]
*
* @var array
*/
private $sender;
/**
* Collection with recipients informations.
* Collection: [
* [ 'name' => 'stewie', 'mail' => 'stewie@griffin.com' ]
* [ 'name' => 'Peter', 'mail' => 'peter@griffin.com' ]
* [ 'name' => 'Lois', 'mail' => 'lois@griffin.com' ]
* [ 'name' => 'Chris', 'mail' => 'chris@griffin.com' ]
* [ 'name' => 'Brian', 'mail' => 'brian@griffin.com' ]
* // No one care about Meg
* ]
* @var Collection
*/
private $recipients;
/**
* Mail view template.
*
* @var String
*/
private $template;
/**
* Collection with other attributes for the view.
*
* @var mixex
*/
public $attributes;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($sender, $recipients, $template, $attributes)
{
$this->sender = $sender;
$this->email = $recipients;
$this->template = $template;
$this->attributes = $attributes;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
// Senders addresses
$this->from($this->sender['name'], $this->sender['mail']);
// Recipients addresses
foreach($recipients as $recipient) {
$this->to($recipient['name'], $recipient['mail']);
}
// Subject
$this->subject("Richiesta informazioni");
// Return view
return $this->view($this->template);
}
}
Come potete vedere la classe contiene tre variabili private ($sender
, $recipients
, $template
) e una variabile pubblica $attributes
. Le classi Mailable
hanno questa caratteristica (vedi la documentazione.
any public property defined on your mailable class will automatically be made available to the view.
Tradotto:
qualsiasi proprietà pubblica definita nella tua classe verrà resa automaticamente disponibile alla view.
Quindi, nella view descritta di seguito, avrò a disposizione un array $attributes
che conterrà tutte le variabili dinamiche da passare ad un determinato template, a differenza delle variabili $sender
, $recipients
, $template
, utilizzate solo per impostare la testata della mail. Ovviamente dato che de gustibus non est disputandum, se avete suggerimenti o volete aggiungere la vostra implementazione della classe, vi invito a continuare la discussione!
contact.blade.php
<meta charset=""UTF-8"">
<h4>Nuova richiesta informazioni da parte di {{ $attributes['name'] }}</h4>
{{ $attributes['name'] }} ti ha invito il seguente messaggio:
{{ {{ $attributes['message'] }} }}
<h4>Ulteriori informazioni:</h4>
<ul>
@foreach($attributes['infos'] as $key => $info)
<li><strong>{{ $key }}:</strong> {{ $info }}</li>
@endforeach</ul>
Il Test
La pausa caffè sta per terminare, quindi verifichiamo che tutto funzioni creando un piccolo controller, richiamato, ad esempio, da un form di richiesta informazioni.
namespace AppHttpControllers;
use IlluminateHttpRequest;
use AppHttpRequests;
use Mail;
use Collection;
use AppMailContact;
class MailController extends Controller
{
public function contact(Request $request)
{
// validation and other stuff...
[...]
// sender
$sender = [ 'name' => $request->name, 'mail' => $request->mail ];
// recipients
$recipients = new Collection;
$recipients->push(['name' => 'Laravel Italia', 'mail' => 'info@laravel-italia.it']);
// attributes
$attributes = [
'name' => $request->name,
'message' => $request->message,
'infos' => [
'telefono' => $request->phone,
'indirizzo' => $request->address,
// [...]
]
];
Mail::send(new Contact($sender, $recipients, 'mail.contact', $attributes));
// return result
[...]
}
}
Questo controller si occuperà di inviare la mail, richiamando il metodo build()
della classe Contact
, il risultato? Beh guardate la casella di posta per scoprirlo!
… ed ora?
Cosa ne pensate di queste feature? Implementate anche voi le classi Mailable
o lavorate in maniera differente?
In questo articolo ho tralasciato la parte di configurazione dei vari driver mail, l’aggiunta di allegati e l’invio tramite una coda. Se volete avere maggiori informazioni riguardo questi argomenti, vi invito a continuare la discussione in tutti i canali di Laravel Italia così da riuscire rendere più completo l’esempio proposto!
Fateci sapere cosa ne pensate, e non dimenticate che c’è sempre il nostro bellissimo Slack, pieno di gente che discute del framework più bello del mondo!