Laravel: Envío de mails con Formulario (parte 21)
Archivos:
- resources/views/layouts/header.blade.php
Agregaremos al menú de navegación un link «contáctanos». Al pulsarlo, nos redirigirá a una vista que mostrará un formulario donde poner el nombre, el mail y un mensaje. Esa información nos será enviada en un correo electrónico.
Enlace en el menú
Abrimos la platilla de headers dentro de la carpeta partials, para añadir un link «contactanos» en nuestro menú de navegación.
<ul>
<li><a href="{{route('home')}}" class="{{request()->routeIs('home') ? 'active' : '' }}">Home</a>
{{-- @dump(request()->routeIs('home')) --}}
</li>
<li><a href="{{route('cursos.index')}}" class="{{request()->routeIs('cursos.*') ? 'active' : '' }}">Cursos</a>
{{-- @dump(request()->routeIs('cursos.index')) --}}
</li>
<li><a href="{{route('nosotros')}}" class="{{request()->routeIs('nosotros') ? 'active' : '' }}">Nosotros</a>
{{-- @dump(request()->routeIs('nosotros')) --}}
</li>
<li><a href="">Contactanos</a>
</li>
</ul>
Ruta para almacenar mail
Abrimos web.php. Le damos a la ruta get que hemos creado para enviar mails el nombre «contactanos.index».
Route::get('contactanos', function() {
$correo = new ContactanosMailable;
Mail::to('weblikonet@gmail.com')->send($correo);
return "mensaje enviado";
})->name('contactanos.index');
Ruta para mostrar el formulario
Hacemos que el nuevo enlace de contacto apunte a esa ruta.
<li><a href="{{route('contactanos.index')}}">Contactanos</a></li>
Controlador para la ruta y métodos
Creamos un controlador para que administre la ruta.
php make:controller ContactanosController
Creamos dos métodos para este controlador: index() para mostrar el formulario y store() para procesarlo y enviar el mail.
class ContactanosController extends Controller
{
//
public function index(){
}
public function store(){
}
}
Modificamos el controlador
Habíamos escrito esta función en la ruta:
$correo = new ContactanosMailable;
Mail::to('weblikonet@gmail.com')->send($correo);
return "mensaje enviado";
Lo ponemos esta vez dentro del método store().
class ContactanosController extends Controller
{
//
public function index(){
}
public function store(){
$correo = new ContactanosMailable;
Mail::to('weblikonet@gmail.com')->send($correo);
return "mensaje enviado";
}
}
Como estamos creando aquí el objeto y haciendo uso de la clase, debemos importar las clases en el controlador:
use App\Mail\ContactanosMailable;
use Illuminate\Support\Facades\Mail;
Modificamos la ruta para el controlador
Modificamos la ruta para que llame al método index() del controlador ContactanosController:
Route::get('contactanos', [ContactanosController::class, 'index'])->name('contactanos.index');
Vista para el formulario
Hacemos que el método index() del controlador devuelva una vista llamada «contactanos.index»:
public function index(){
return view('contactanos.index');
}
Creamos una carpeta dentro de views llamada «contactanos» y, dentro, la vista index.blade.php. Su contenido puede estar copiado de la vista home, y modificamos a nuestro antojo el title y el h1:
@extends('layouts.plantilla')
@section('title', 'Contactanos')
@section('content')
<h1>Déjanos un mensaje</h1>
@endsection
Añadimos la clase para que el enlace quede activo cuando se visite:
<a href="{{route('contactanos.index')}}" class="{{request()->routeIs('contactanos.index') ? 'active' : '' }}">Contactanos</a>
Formulario de contacto
Creamos el formulario dentro de la vista:
<form action="">
<label>
Nombre:
<br>
<input type="text" name="name">
</label>
<br>
<label>
Correo:
<br>
<input type="mail" name="email">
</label>
<br>
<label>
Mensaje:
<br>
<textarea name="mensaje" rows="4"></textarea>
</label>
<br>
<button type="submit">Enviar mensaje</button>
</form>
Ruta post para el formulario
Creamos una ruta que procese la información del formulario. Va a ser de tipo post y llevará la url «contactanos». Le asignamos el método store() del controlador ContactanosController. Le damos el nombre «contactanos.store»:
Route::post('contactanos',[ContactanosController::class, 'store'])->name('contactanos.store');
Ponemos esta ruta en el action del formulario. Tenemos que especificar también el método del formulario, y el token csrf:
(...)
<form action="{{route('contactanos.store')}}" method="post">
@csrf
(...)
Ejercicio
Hagamos este pequeño ejercicio antes de continuar. Si añadimos una propiedad a la clase del mailable que hemos creado para enviar el correo, como esta:
(...)
class ContactanosMailable extends Mailable
{
use Queueable, SerializesModels;
public $subject="Asunto del mail de contacto";
public $propiedad="Esta es una propiedad del mailable";
(...)
Podemos rescatar esta propiedad dentro de la vista del mail de la siguiente forma:
<!DOCTYPE html>
(...)
<body>
<h1>Correo Electrónico</h1>
<p>Primer mail que mando por Laravel</p>
{{$propiedad}}
</body>
</html>
Y comprobar que se envía correctamente
Recuperar la información del formulario
Al método store del controlador le pasamos el objeto request.
public function store(Request $request){
$correo = new ContactanosMailable;
Mail::to('weblikonet@gmail.com')->send($correo);
return "mensaje enviado";
}
Donde estoy creando la instancia de la clase ContactanosMailable le pasamos la información de request al constructor:
public function store(Request $request){
$correo = new ContactanosMailable($request->all());
Mail::to('weblikonet@gmail.com')->send($correo);
return "mensaje enviado";
}
Y recibimos la información en el constructor de la clase de la siguiente forma:
public $contacto;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($contacto)
{
$this->contacto = $contacto;
}
Ahora podemos modificar la vista para imprimir la información así:
(...)
<body>
<h1>Correo Electrónico</h1>
<p>Primer mail que mando por Laravel</p>
{{$propiedad}}
<p><strong>Nombre:</strong> {{$contacto['nombre']}}</p>
<p><strong>Nombre:</strong> {{$contacto['email']}}</p>
<p><strong>Nombre:</strong> {{$contacto['mensaje']}}</p>
</body>
</html>
Validación
Completamos el método store() para validar el formulario. Todos los campos serán requeridos y el email debe ser un email:
public function store(Request $request){
$request->validate([
'name'=>'required',
'name'=>'required|email',
'mensaje'=>'required',
]);
$correo = new ContactanosMailable($request->all());
Mail::to('weblikonet@gmail.com')->send($correo);
return "mensaje enviado";
}
En el formulario ponemos los mensajes de error en cada campo. Abrimos la directiva error con el parámetro el nombre del campo que queramos validar, y en la directiva un párrafo con el posible error almacenado en la variable $message. Lo hacemos en cada campo:
<form action="{{route('contactanos.store')}}" method="POST">
@csrf
<label>
Nombre:
<br>
<input type="text" name="name">
</label>
<br>
@error('name')
<p><strong>{{$message}}</strong></p>
@enderror
<label>
Correo:
<br>
<input type="mail" name="email">
</label>
<br>
@error('email')
<p><strong>{{$message}}</strong></p>
@enderror
<label>
Mensaje:
<br>
<textarea name="mensaje" rows="4"></textarea>
</label>
<br>
@error('mensaje')
<p><strong>{{$message}}</strong></p>
@enderror
<button type="submit">Enviar mensaje</button>
</form>
Redirección
Con esta redirección no mostraremos el mensaje «mensaje enviado», sino que volveremos a la vista en la que estábamos mostrando un mensaje. Le mandamos a la ruta un mensaje de sesión con el método with con dos parámetros, el nombre de la variable y su contenido.
public function store(Request $request){
$request->validate([
'name'=>'required',
'email'=>'required|email',
'mensaje'=>'required',
]);
$correo = new ContactanosMailable($request->all());
Mail::to('weblikonet@gmail.com')->send($correo);
return redirect()->route('contactanos.index')->with('info','mensaje enviado');
}
Usamos un condicional en la vista para ver si mostramos o no la variable de sesión en una alerta, en la vista del formulario.
(...)
<button type="submit">Enviar mensaje</button>
</form>
@if (session('info'))
<script>
alert("{{session('info')}}")
</script>
@endif
(...)
Recursos:
Enlace de Youtube: https://www.youtube.com/watch?v=Ei3RVhdcE0A&list=PLZ2ovOgdI-kWWS9aq8mfUDkJRfYib-SvF&index=29