Introduzione
Nei precedenti articoli, abbiamo visto come progettare un sito tramite Gatsby, un framework basato su React. Abbiamo concentrato l'attenzione sull'aspetto visuale del progetto, ovvero il front end, tralasciando ciò che concerne l'aspetto elaborativo, ossia il back end. In questo articolo, vedremo come utilizzare il linguaggio PHP per creare un servizio REST per l'invio di una e-mail e come invocarlo da un componente React, in particolare da una pagina che permetterà l'invio di messaggi.
Prerequisiti
Per poter invocare un servizio REST possiamo utilizzare la libreria
Axios che facilita notevolmente questo tipo di chiamate. Per installare la libreria, eseguiamo questo comando:
Creazione della pagina dei contatti
Iniziamo con la scrittura del codice per la nuova pagina che servirà per inviare un messaggio al proprietario o all'amministratore del sito. all'interno della directory
pages creiamo due file:
- - contacts.js: è la pagina attraverso la quale inviare il messaggio;
- - contacts.module.scss: è il file con gli stylesheets.
Nel file
contacts.js inseriamo il codice per definire la pagina per la richiesta di informazioni da inviare:
import React, { Component } from 'react';
import Layout from '../components/layout'
import axios from 'axios';
import * as styles from "./contacts.module.scss"
// ATTENZIONE:
// il valore di questa costante deve essere modificato in modo che corrisponda
// alla directory nella quale sarà posto lo script PHP per il servizio REST
const API_PATH = 'http://localhost:8000/api/index.php';
class Contacts extends Component {
constructor(props) {
super(props);
this.state = {
name: '',
email: '',
subject: '',
message: '',
mailSent: false,
error: null
}
}
handleFormSubmit(event) {
event.preventDefault();
axios({
method: 'post',
url: `${API_PATH}`,
headers: { 'content-type': 'application/json' },
data: this.state
})
.then(result => {
this.setState({
mailSent: result.data.sent
})
})
.catch(error => {
this.setState({ error: error.message })
});
}
render() {
return (
<Layout>
<div className={styles.contacts}>
<form action="#">
<div className={styles.settings}>
<label className={styles.form} htmlFor="name">
Nome:
</label>
<input className={styles.form} type="text" name="name" id="name"
value={this.state.name}
onChange={e => this.setState({ name: e.target.value })}
/>
<label className={styles.form} htmlFor="email">
Email:
</label>
<input className={styles.form} style={{ padding: "5px", marginTop: "-6px" }}
type="email" name="email" id="email"
value={this.state.email}
onChange={e => this.setState({ email: e.target.value })}
/>
<label className={styles.form} htmlFor="subject">
Oggetto:
</label>
<input className={styles.form} style={{ padding: "5px", marginTop: "-6px" }}
type="text" name="subject" id="subject"
value={this.state.subject}
onChange={e => this.setState({ subject: e.target.value })}
/>
<label className={styles.form} htmlFor="message">
Messaggio:
</label>
<textarea className={styles.form} style={{ padding: "5px", marginTop: "-6px" }}
name="message" id="message" rows="5"
value={this.state.message}
onChange={e => this.setState({ message: e.target.value })}
/>
</div>
<br />
{!this.state.mailSent &&
<div className={styles.buttons}>
<button className={styles.form} type="submit" onClick={e => this.handleFormSubmit(e)} >
Invia
</button>
</div>
}
<div>
{this.state.mailSent &&
<div className={styles.thanks}>Grazie per aver inviato il messaggio.</div>
}
</div>
</form>
<br />
</div>
</Layout >
)
}
}
export default Contacts
Alcune osservazioni sul codice:
- - il valore della costante API_PATH deve essere modificato in modo che corrisponda alla directory nella quale sarà posto lo script PHP per il servizio REST;
- - la form richiede il nome di chi sta inviando il messaggio, il suo indirizzo mail, l'oggetto e il messaggio;
- - la callback handleFormSubmit è il punto in cui viene utilizzata la libreria Axios per la chiamata al servizio REST:
- - la chiamata è di tipo POST e il body della richiesta è lo stato della pagina, le cui informazioni riflettono i dati richiesti nella form;
- - l'aggiornamento dello stato avviene sfruttando l'evento onChange dei singoli campi: in questo modo, alla pressione del pulsante Invia lo stato è aggiornato e pronto per essere utilizzato da Axios
- - quando si preme Invia entra in gioco la callback handleFormSubmit che richiama lo script PHP definito dalla costante API_PATH, che analizzeremo tra poco.
Nel file
contacts.module.scss inseriamo il codice per gli sylesheets utilizzati in
contacts.js:
.contacts {
margin-top: 30px;
font-family: Roboto;
font-size: 12pt;
line-height: 16px;
background-color: #cccccc;
padding-top: 30px;
padding-bottom: 10px;
padding-left: 10px;
}
div.settings {
display: grid;
grid-template-columns: 100px 400px;
grid-gap: 10px;
}
label.form {
font-family: Roboto;
}
input.form {
font-family: Roboto;
padding: 5px;
margin-top: -6px;
}
textarea.form {
font-family: Roboto;
padding: 5px;
}
button.form {
font-family: Roboto;
}
div.buttons {
width: 510px;
overflow: hidden;
text-align: right;
}
div.settings label {
text-align: right;
}
.thanks {
font-family: Roboto;
font-size: 12pt;
font-style: italic;
}
Back end PHP
I file legati al back end li andremo a mettere in una directory interna a
static. Dentro la directory
static creiamo la directory
api e, al suo interno, una ulteriore directory
contacts; in questo modo avremo una directory per ciascuna funzionalità che ha bisogno di esser gestita da back end. All'interno di
contacts andremo a creare il file
index.php con la logica necessaria alla validazione dei dati e all'invio della mail all'amministratore o al proprietario del sito.
Il contenuto di
index.php è:
<?php
header("Access-Control-Allow-Origin: *");
$rest_json = file_get_contents("php://input");
$_POST = json_decode($rest_json, true);
if (empty($_POST['name']) && empty($_POST['email'])) die();
if ($_POST)
{
http_response_code(200);
$name = $_POST['name'];
$from = $_POST['email'];
$subject = $_POST['subject'];
$message = $_POST['message'];
// Indirizzo a cui inviare la mail con i dati forniti nella pagina Contacts
$to = "info@mioblog.abc";
// Dati da includere nella mail
$msg = "Messaggio da: " . $name . "\r\n".
"Mail: " . $from . "\r\n".
"Oggetto: " . $subject . "\r\n".
"Messaggio: " . $message;
// Headers
$headers = "MIME-Version: 1.0";
$headers.= "Content-type: text/html; charset=UTF-8";
$headers.= "From: <contatti@www.moschini.cloud>";
// Invio mail
mail($to, "dalla pagina Contacts del blog", $msg, $headers);
echo json_encode(array(
"sent" => true
));
}
else
{
echo json_encode(["sent" => false, "message" => "Qualcosa è andato storto ..."]);
}
?>
Analizziamo lo script PHP:
- - il body della richiesta POST viene recuperato tramite:
$rest_json = file_get_contents("php://input");
e quindi trasformato in JSON:
$_POST = json_decode($rest_json, true);
- - se il nome e l'indirizzo e-mail sono entrambi non valorizzati, il servizio termina senza segnalare errori:
if (empty($_POST['name']) && empty($_POST['email'])) die();
altrimenti si recuperano le informazioni indicate nella form e si utilizzano per comporre il contenuto della mail che verrà inviata all'indirizzo specificato nella variabile
$to;
- - infine, si invoca il metodo per l'invio della mail:
mail($to, "dalla pagina Contacts del blog", $msg, $headers);
e si valorizza l'attributo
sent a true, in modo da essere recepito come risultato della chiamata al servizio REST;
Non resta che aggiungere il link alla pagina
Contacts nella navigation bar definita nel componente
Header per poter testare la form per l'invio dei messaggi. Per questo, nel file
header.js aggiungiamo questa linea:
<li>
<Link to="/contacts/"
activeClassName={styles.navigationActive}
className={styles.navigation}
>
Contacts
</Link>
</li>
all'interno del tag
<ul className={styles.navigation}>
...
<li>
<Link to="/contacts/"
activeClassName={styles.navigationActive}
className={styles.navigation}>
Contacts
</Link>
</li>
</ul>
Quindi, l'interfaccia della navigation bar presenta un nuovo link
Contacts che apre la pagina per l'invio dei messaggi:
Dopo aver compilato le informazioni richieste, al click su
Invia, se non ci sono errori, si visualizza il messaggio di avvenuto invio della e-mail: