ACF: Créer un Formulaire de Connexion, Inscription & Compte en AJAX grâce à ACF Form
ACF Form permet de créer des formulaires ACF à afficher en front-end. Avec le Contenu Flexible, c’est l’une des fonctionnalités les plus pratiques du plugin. Dans ce tutoriel nous allons utiliser toute la puissance de cette feature pour créer des fomulaires de connexion, d’inscription, de mot de passe perdu et de modification de compte. Cerise sur la gâteau, tous les formulaires sont optimisés pour Bootstrap 4.
Démarrage
Introduction à ACF Form
Pour comprendre les différentes étapes de ce tutoriel, il est nécessaire de saisir le fonctionnement natif de ACF Form. Comme la plupart des fonctions Advanced Custom Fields, acf_form()
peut être appelé depuis n’importe quelle page de votre installation WordPress. Cette fonction va se charger d’afficher, valider et soumettre un formulaire de la même manière que dans le back-office, mais en front. Son champ d’action est vaste: Création/mise à jour de contenu, d’options, d’utilisateurs et bien plus!
Le premier paramètre de la fonction acf_form()
est sans doute le plus important, il s’agit du post_id
. Celui-ci va définir la “cible” de votre formulaire. ACF Form embarque déjà tout un tas de possibilité à ce niveau. Par exemple, post_id = 'new_post'
va créer un formulaire de création de post. post_id = 'post_384'
va automatiquement créer un formulaire de mise à jour de post, et il en va de même avec 'user_10'
pour un utilisateur en particulier ou encore 'term_51'
pour un terme de taxonomie.
Une fois le paramètre post_id
défini, ACF Form va automatiquement afficher un formulaire avec tous les champs attribués à un post
, un user
ou un term
. Les règles de validation entrées dans l’administration de ce groupe de champs seront aussi appliqués. Par exemple, un champ requis sera automatiquement requis via acf_form()
, il en va de même pour les valeurs par défaut.
Tout comme dans le back-office, lorsque le formulaire est soumis par l’utilisateur, ACF lance une première requête AJAX afin de valider les champs. Si une erreur survient, alors la soumission est stoppé et un message s’affiche à côté du champ qui pose problème. Si la validation se termine correctement, alors le formulaire est définitivement soumis, la page se recharge et un message de succès apparait.
Créer un formulaire personnalisé
Il est aussi possible de choisir soit même les champs à afficher, afin de complètement contrôler les informations d’un formulaire. Pour cela nous avons à disposition deux arguments:
field_groups
qui permet d’afficher tous les champs d’un groupe de champs en particulier.fields
qui permet d’afficher uniquement certains champs en particulier, peu importe son groupe de champs.
Ces deux paramètres priment sur les champs détectés automatiquement par post_id
.
Créer sa propre logique de soumission
Il est tout à fait possible d’entrer un paramètre post_id
arbitraire. Par exemple:
acf_form(array('post_id' => 'hwk', field_groups = array(5)))
Ce formulaire affichera tous les champs du groupe de champs 5
. Une fois soumis, le formulaire sera validé et traité (champs requis, minimum/maximum etc..). Il n’y aura absolument aucune conséquence de mise à jour ou d’ajout en particulier. Et pour cause, ACF ne sait tout simplement pas à quoi correspond la cible 'hwk'
.
Grâce aux différents hooks intégrés dans le plugin, il est possible de changer cela, et par conséquent, de créer notre propre logique de traitement et de soumission.
Traiter le formulaire en une seule requête Ajax
Afin d’optimiser la rapidité de traitement et d’améliorer l’expérience utilisateur, il est possible de ne passer que par une seule requête Ajax et de ne pas recharger la page. Nous allons pour cela créer notre propre action Ajax, vérifier la validation des champs avec acf_validate_save_post()
, puis traiter nos données.
Compatibilité avec les champs d’upload
La fonction native Ajax de ACF Form n’utilise pas de formData
, par conséquent les champs d’upload de fichiers ou d’images ne fonctionneront pas. C’est pourquoi nous allons ré-écrire la fonction Javascript acf.validation.fetch
.
Création des groupes de champs
Pour bien commencer, nous allons créer plusieurs groupes de champs. Vous pouvez télécharger l’export des groupes de champs ACF en json ici.
Les groupes Connexion
, Inscription
, Mon Compte
& Mot de passe oublié
seront affichés à l’aide de acf_form()
. Ces groupes de champs ne sont pas rattachés à un Post Type en particulier. Par conséquent, il est préférable de les désactiver pour les rendre invisible depuis le back-office.
Configuration générale
Nous allons créer trois fonctions d’aide et appliquer plusieurs hooks afin de créer une configuration générale pour nos formulaires ACF Form Ajax. Voici leur description:
- Deregister ACF Style
acf_form()
importe plusieurs feuilles de styles dès qu’il est appelé sur une page. Nous allons les dé-enregistrer afin de laisser Bootstrap prendre la main sur le style. - Elements Class
Nous ajoutonscol-12 form-group
sur chaque wrapper de champs etform-control
sur les champs. Il est possible d’ajouter ses propres class dans le wrapper des champs depuis l’administration ACF, via le paramètreclass
du champ. - Default Form Args
Nous définissons des paramètres par défaut pour chaque appel deacf_form()
. Cela nous évitera, par exemple, d’ajouter à chaque fois<div class="row">
en début de formulaire. - Elements Required Class
Nous ajoutons ici une classtext-danger
sur les astérisques de champs requis, pour coller avec la style de Bootstrap. - Get Form
Fonction d’aide, qui nous permet de décrypter le$_POST
du formulaire ACF. Nous aurons ainsi accès à tous les paramètres duacf_form()
lors de notre traitement Ajax. - Get Data
Par défaut ACF Form envoi les champs dans des variables$_POST['field_xyz']
(via leurkey
). Cette fonction nous permettra de les traiter à l’aide de leurname
. - Get Return
Une fonction simple mais efficace. Celle-ci va automatiser le traitement du retourjson
: redirection et/ou message de succès.
Configuration des formulaires
Le fonctionnement des différents formulaires est assez similaire, néanmoins chacun d’entre eux aura sa propre configuration. Voici les principaux hooks utilisés:
- ACF Register Form
Chaque formulaire aura sa propre déclaration via la fonctionacf_register_form()
, afin de pré-enregistrer nos argumentsacf_form()
. Nous pourrons par la suite directement appeleracf_form()
avec sonid
. Par exemple, dans notre Template de page Login, nous appellerons:acf_form('hwk_ajax_acf_login')
. - ACF Ajax Validation
L’actionacf/validate_save_post
intervient juste avant le début du traitement des erreurs de ACF Form (/includes/validation.php:271
). Nous allons utiliser ce hook afin de nous glisser dans la requête Ajax et ajouter notre propre logique. Les retoursjson
seront assurés par la fonctionwp_send_json_success()
afin de garantir que le reste de la soumission native de ACF Form sera annulée.- Validation de la requête
La variable$_POST['_acf_post_id']
nous servira à vérifier que le formulaire correspond bien à celui qui nous intéresse. Dans l’exemple du formulaire de Connexion,$_POST['_acf_post_id']
devra être égal à'hwk_ajax_acf_login'
. - Récupération des données
Nous récupérons le formulaire viahwk_acf_form_get_form()
et les données viahwk_acf_form_get_data()
. Ces deux fonctions doivent obligatoirement retourner un tableau, sinon quelques chose cloche. - Gestion des erreurs
acf_form()
utilise les fonctions inhérentes à ACF pour ajouter et récupérer les erreurs de traitement de formulaire. Respectivementacf_add_validation_error()
&acf_get_validation_errors()
. Si la récupération des erreurs retourne des valeurs, alors ACF stop la soumission et retourne unjson
avec pour argument:'valid' => false, 'errors' => array('champ' => 'Message d'erreur')
.
Nous utiliserons aussi cette terminologie pour nos propres erreurs de champs. Néanmoins, dans le cas où la validation des champs est terminé mais qu’une erreur générale se produit (ex: un e-mail n’a pas pu être envoyé), nous utiliserons les arguments'valid' => true, 'data' => array('error' => 'Message d'erreur générale')
. Ce dernier sera traité de manière personnalisé par notre script javascript. - Validation des champs
Ici, nous validons les champs. Comme nous avons accès à toutes les données du formulaire, nous pouvons valider les champs les uns après les autres, ou les uns dépendants des autres. Si un champ ne répond pas à notre logique, nous ajoutons une erreur ciblé à l’aide de la fonctionacf_add_validation_error('acf[field_xyz]', 'Message d'erreur')
. Notez que nos propres règles s’additionnent ici à celles définies dans le Back-office d’ACF: Champ requis, maximum/minimum etc… Pratique!
- Validation de la requête
- ACF Ajax Submit
C’est ici le noyau du traitement de nos données. Cette fonction Ajax sera appelée lorsqu’un formulaire est soumis.- Afin de valider l’authenticité de la requête, nous allons utiliser la fonction
acf_verify_nonce()
. - Nous validons les données à l’aide de
acf_validate_save_post()
qui appel l’actionacf/validate_save_post
. - Lorsque les champs sont validés et que nous avons terminé notre traitement (connexion, création de compte, mise à jour), alors nous envoyons une réponse
json
positive pour faire savoir que tout s’est bien passé.
- Afin de valider l’authenticité de la requête, nous allons utiliser la fonction
Formulaire Connexion
Comme son nom l’indique, le formulaire de Connexion va identifier l’utilisateur en se baant sur son login
et son password
. Sa particularité est d’ajouter un champ caché redirect
. Ce champ sera pré-rempli par la variable $_GET['redirect']
, si celle-ci existe.
Ainsi nous pourrons rediriger l’utilisateur identifié vers une adresse dynamiquement définie. Typiquement l’adresse de la page que l’utilisateur visitait avant de s’identifier. Afin d’ajouter manuellement un champ <input type="hidden" />
nous allons passer par l’action acf/input/form_data
.
Configuration de groupe de champs ACF Connexion
:
- Label:
Login
/ Nom:login
/ Type:Texte
- Label:
Mot de passe
/ Nom:password
/ Type:Mot de passe
- Label:
<vide>
/ Nom:remember
/ Type:Select
/ Valeur:remember_me : Se souvenir de moi
Formulaire Mot de passe oublié
Ce formulaire est assez similaire au formulaire de Connexion
. Au lieu d’identifier l’utilisateur, il lui envoie un e-mail de ré-initialisation de mot de passe. Malheureusement, il n’y a aucun moyen d’appeler la fonction native de WordPress, car celle-ci se situe dans le fichier wp-login.php
.
Pour pallier à ce problème, nous allons copier/coller la partie qui nous intéresse et notamment les filtres retrieve_password_title
& retrieve_password_message
. Ainsi nous sommes sûr que notre script reste compatible avec les autres plugins.
Configuration du groupe de champs ACF Mot de passe oublié
:
- Label:
E-mail
/ Nom:email
/ Type:E-mail
Formulaire d’Inscription
Le formulaire d’inscription est probablement le formulaire le plus complexe. En plus d’enregistrer et d’identifier un utilisateur à la volée, celui-ci doit aussi exécuter le reste de la soumission native de acf_form()
afin d’enregistrer les autres champs de type user_meta
. Dans notre exemple, ce processus est symbolisé par le champ Commentaire
, à la fois présent dans le groupe de champs Inscription
et dans le groupe de champs Utilisateur
.
Pour laisser ACF Form reprendre en main lors de la seconde partie du processus d’enregistrement, nous allons utiliser toutes les données du formulaire soumis, mais en modifiant le post_id
et le return
. Ainsi, le post_id
deviendra 'user_5'
(ID
de l’utilisateur fraichement crée), et return
passera à null
pour éviter toute redirection dans notre requête Ajax.
Nous utiliserons une nouvelle instance de class new acf_form_front()
et appellerons la méthode acf()->form_front->submit_form($form)
afin que ACF mette à jour l’utilisateur, si besoin. Notez qu’il est important que le champ qui sert de symbolique à l’user_meta
soit nommé de la même façon dans le groupe de champs Inscription
& Utilisateur
.
Configuration du groupe de champs ACF Inscription
:
- Label:
Login
/ Nom:login
/ Type:Texte
- Label:
E-mail
/ Nom:email
/ Type:E-mail
- Label:
Mot de passe
/ Nom:password
/ Type:Mot de passe
- Label:
Mot de passe (vérification)
/ Nom:password_check
/ Type:Mot de passe
- Label:
Commentaire
/ Nom:comment
/ Type:Texte
Formulaire Mon Compte
Le formulaire Mon Compte
permet a un utilisateur identifié de modifier son profil. Il est assez proche du formulaire Inscription
. Néanmoins il nécessite de pré-remplir les champs du formulaire avec les données de l’utilisateur. Pour y parvenir pour allons appliquer un filtre sur acf/load_value
en utilisant les données renvoyées par wp_get_current_user()
.
Configuration du groupe de champs ACF Mon compte
:
- Label:
E-mail
/ Nom:email
/ Type:E-mail
- Label:
Nouveau mot de passe
/ Nom:password
/ Type:Mot de passe
- Label:
Nouveau mot de passe (vérification)
/ Nom:password_check
/ Type:Mot de passe
- Label:
Commentaire
/ Nom:comment
/ Type:Texte
Les Templates de Pages
Maintenant que tous formulaires sont configurés, nous pouvons appeler les formulaires via acf_form('id')
dans nos pages. Voici deux exemples, en respectant la syntaxe Bootstrap 4.
Page de connexion
Page Mon Compte
Les scripts Javascript
Nous commençons par ré-écrire la fonction acf.validation.fetch
afin d’utiliser un formData
pour être compatible avec les champs d’upload. Afin de gérer les retours json
envoyés par nos requêtes Ajax, nous avons besoin de définir différents hooks Javascripts: validation_begin
, add_field_error
& validation_complete
.
La feuille de Style CSS
Les hooks de Templating & Redirections
Pour parfaire l’expérience utilisateur de nos pages, nous allons définir des redirections. Nous utilisons pour cela l’action template_redirect
. Afin d’éviter de créer une nouvelle page pour le formulaire Mot de passe oublié
, nous réutiliserons la page de Connexion
en attribuant une query_var
. Enfin, nous ajouterons une logique sur les menu pour afficher des éléments logiques par rapport au statut du visiteur (identifié/non-identifié).