Créer un système de notation (rating/reviews) sur wordpress sans pugin

Comment créer un système de notation interne sur wordpress ?

Dans ce tuto, on va voir comment mettre en place un système de notation simple, sans faire appel à un plugin. La plupart des plugins de notation sont de vrais systèmes intégrés, avec la création à la volée de custom post types, la possibilité pour l’utilisateur de noter ou de commenter via un formulaire, etc. Ce sont des solutions tout en un qui facilitent le travail des non développeurs, mais en réalité peu personnalisables.

Pour un besoin plus modeste, on va créer un système de notation propre, notamment grâce à la fonction wp_star_rating() intégrée d’office dans wordpress !

Ce dont on va avoir besoin :

  • un custom post type « avis » (cela marche aussi sur des articles bien sûr)
  • ACF dans sa version gratuite, pour générer des metabox additionnelles pour nos différentes notes.
  • Le codex pour le code de base.

Le codex et la fonction wp_star_rating( $args )

En fouillant un peu, on découvre en effet que wordpress dispose déjà d’une fonction dédiée à la notation par étoiie, d’où son nom : wp_star_rating !  Le codex explique brièvement comment l’implémenter sur son site. On va donc voir comment s’en servir.

Prérequis :

Selon le codex :   » In order to use this function on the front end, your template must include the wp-admin/includes/template.php file and enqueue the appropriate dashicons CSS font information. »

L’appel du fichier template.php

On commence donc par appeler le fichier requis, avec ce bout de code à insérer dans le fichier functions.php

require_once( ABSPATH . 'wp-admin/includes/template.php' );

L’utilisation de la fonction

L’exemple donné un peu partout est le suivant :

if ( !function_exists( 'wp_star_rating' ) ) { 
require_once ABSPATH . '/wp-admin/includes/template.php';
}

// Optional. Array of star ratings arguments.
$args = array(
'rating' => 0,
'type' => 'rating',
'number' => 0
);

// NOTICE! Understand what this does before running.
$result = wp_star_rating($args);

Le style

Toujours selon le codex, cette fonction fait appel à la police Dashicon, et la doc recommande donc de l’installer ou de faire appel à ces icônes. Voici en bonus, le style par défaut donné en exemple. Ici, on voit qu’on a trois icônes, une étoile vide, une deuxième à moitié pleine, et une troisième entièrement colorée. Ces différentes icônes sont clairement nommées via les classes :

  • star-full
  • star-half
  • star-empty

Elles vont servir à indiquer la notation, puisque selon le codex, les chiffres sont « expressed in either a 0.5 rating increment, or percentage.« . Le 0.5 sera donc défini par l’icone à moitié vide dont la classe est « star-half ».

@font-face {
font-family: "dashicons";
src: url("../fonts/dashicons.eot");
}

@font-face {
font-family: "dashicons";
src: url(data:application/x-font-woff;charset=utf-8;base64,/* !! Large amount of data removed, see wp-includes/css/dashicons.css for complete data !! */) format("woff"),
url("../fonts/dashicons.ttf") format("truetype"),
url("../fonts/dashicons.svg#dashicons") format("svg");
font-weight: normal;
font-style: normal;
}

.star-rating .star-full:before {
content: "\f155";
}

.star-rating .star-half:before {
content: "\f459";
}

.star-rating .star-empty:before {
content: "\f154";
}

.star-rating .star {
color: #0074A2;
display: inline-block;
font-family: dashicons;
font-size: 20px;
font-style: normal;
font-weight: 400;
height: 20px;
line-height: 1;
text-align: center;
text-decoration: inherit;
vertical-align: top;
width: 20px;
}

Voilà, maintenant qu’on a les prérequis, on peut commencer !

Un exemple concret d’utilisation

Pour notre exemple, on va partir d’un besoin simple : dans notre site, l’utilisateur final doit pouvoir manuellement ajouter des notes à ses articles ou custom post type.

Ces notes seront affichées de différentes manières en fonction de la page : une note sur des vignettes, des étoiles ou des ronds sur une page archive.

Voici le rendu souhaité : à travers un widget qui affiche des vignettes en slider. Ici on a un simple chiffre.

wp_star_rating( $args ) examples

Et ici dans une page archive, avec des vignettes les unes à la suite des autres. Ici on a à la fois le même chiffre et en plus des icônes.

wp_star_rating( $args ) examples

Problématique

Quand on est face à une demande similaire, on peut se demander comment on va faire pour avoir d’un côté :

  • une notation avec des chiffres
  • Une notation avec des chiffres, et en dessous des notes représentées par des icônes.

L’admin doit pouvoir insérer manuellement ces données, mais l’idéal c’est que la note chiffrée soit la moyenne, calculée automatiquement, des notes affichées par thème.

On va donc imaginer dans un custom post type  par exemple, un champ additionnel dans lequel l’admin insérera une notation chiffrée, de 1 à 5.

Puis on va imaginer trois champs additionnels pour les thème « Animation » / « Contenu » / « Organisation ». L’admin devra là aussi insérer manuellement une note, de 1 à 5.

Puisque la note chiffrée on la retrouve un peu partout sur le site, autant prévoir un champ automatisé, qui serait la moyenne des 3 autres notes insérées manuellement..

Création d’un custom post type

Commençons d’abord par créer notre custom post type « avis ». Celui ci dispose ici de deux taxonomies que je met ici, mais pour notre exemple, on en aura pas besoin.


/*AVIS*/
function cc_cpt_review() {
/* Formation */
$labels = array(
'name' => _x('Avis', 'Post Type General Name', 'text_domain'),
'singular_name' => _x('Avis', 'Post Type Singular Name', 'text_domain'),
'menu_name' => _x('Avis', 'text_domain'),
'name_admin_bar' => _x('Avis', 'text_domain'),
'all_items' => _x('Tous les Avis', 'text_domain'),
'add_new_item' => _x('Ajouter un nouvel Avis', 'text_domain'),
'add_new' => _x('Ajouter', 'text_domain'),
'new_item' => _x('Nouvel avis', 'text_domain' ),
'edit_item' => _x('Editer l\'avis', 'text_domain'),
'update_item' => _x('Mettre à jour l\'avis', 'text_domain'),
'view_item' => _x('Voir l\'avis', 'text_domain'),
'search_items' => _x('Rechercher un avis', 'text_domain'),
'not_found' => _x('Aucun avis trouvé', 'text_domain'),
'not_found_in_trash' => _x('Aucun avis trouvé dans la corbeille', 'text_domain'),
);

$args = array(
'label' => _x('Avis', 'text_domain'),
'description' => _x('Avis', 'text_domain'),
'labels' => $labels,
'supports' => array('title', 'editor', 'thumbnail', 'comments', 'revisions', 'custom-fields'),
'hierarchical' => false,
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'menu_position' => 5,
'menu_icon' => 'dashicons-admin-home',
'show_in_admin_bar' => true,
'show_in_nav_menus' => true,
'can_export' => true,
'has_archive' => false,
'exclude_from_search' => false,
'publicly_queryable' => true,
'query_var' => 'avis',
'rewrite' => array( 'slug' => 'tous-les-avis' ),
'capability_type' => 'post',
'show_in_rest' =>'true',
);
register_post_type('avis', $args);
}
add_action('init', 'cc_cpt_review', 10);



function cc_add_taxonomies_review() {
// Catégorie de série
$labels_cat_avis = array(
'name' => _x( 'Catégories de l\'avis', 'taxonomy general name'),
'singular_name' => _x( 'Catégories de l\'avis', 'taxonomy singular name'),
'search_items' => __( 'Rechercher une catégorie'),
'popular_items' => __( 'Catégories populaires'),
'all_items' => __( 'Toutes les catégories'),
'edit_item' => __( 'Editer une catégorie'),
'update_item' => __( 'Mettre à jour une catégorie'),
'add_new_item' => __( 'Ajouter une nouvelle catégorie'),
'new_item_name' => __( 'Nom de la nouvelle catégorie'),
'add_or_remove_items' => __( 'Ajouter ou supprimer une catégorie'),
'choose_from_most_used' => __( 'Choisir parmi les catégories les plus utilisées'),
'not_found' => __( 'Pas de catégories trouvée'),
'menu_name' => __( 'Catégorie d\'avis'),
);

$args_cat_avis = array(

'hierarchical' => true,
'labels' => $labels_cat_avis,
'show_ui' => true,
'show_in_rest' => true,
'show_admin_column' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'categories-avis' ),
);

register_taxonomy( 'categories-avis', 'avis', $args_cat_avis );
}
add_action( 'init', 'cc_add_taxonomies_review', 0 );

function cc_avis_level_taxonomies() {

$labels_level_avis = array(
'name' => _x( 'Niveaux de l\'avis', 'taxonomy general name'),
'singular_name' => _x( 'Niveau de l\'avis', 'taxonomy singular name'),
'search_items' => __( 'Rechercher un avis'),
'popular_items' => __( 'Niveaux populaires'),
'all_items' => __( 'Tous les Niveaux'),
'edit_item' => __( 'Editer un niveau'),
'update_item' => __( 'Mettre à jour un niveau'),
'add_new_item' => __( 'Ajouter un nouveau niveau'),
'new_item_name' => __( 'Nom de le nouveau niveau'),
'add_or_remove_items' => __( 'Ajouter ou supprimer un niveau'),
'choose_from_most_used' => __( 'Choisir parmi les niveaux les plus utilisés'),
'not_found' => __( 'Pas de niveau trouvé'),
'menu_name' => __( 'Niveau de l\'avis'),
);

$args_level_avis = array(

'hierarchical' => true,
'labels' => $labels_level_avis,
'show_ui' => true,
'show_in_rest' => true,
'show_admin_column' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'niveau-avis' ),
);

register_taxonomy( 'niveau-avis', 'avis', $args_level_avis );
}
add_action( 'init', 'cc_avis_level_taxonomies', 0 );

Une fois crée, on retrouve notre CPT (custom post type) donc dans le backoffice du site, et on peut commencer à remplir des « avis », comme on le ferait pour un article.

Mais avant cela, on va créer des champs additionnels pour nos « avis » grâce à ACF.

Création de meta box ACF

On va donc créer un groupe de champs propre à nos « avis ». A l’intérieur, le premier champ à créer sera la « note » globale. On choisit comme type de champ : « Nombre« .

acf number field

On va ensuite créer nos trois autres notes »Animation », « Contenu » et « Organisation ».

acf number field

Ce sont également des champs de type « nombre« , sauf que cette fois on précise une valeur minimale de 1 et une note maximale de 5.

acf number field

Pour finir, on n’oublie pas de préciser que le groupe de champs ne devra apparaître que dans le « type de publication » – « Avis »

acf number field

Pour le type de publication, on peut faire un peu ce qu’on veut, ça dépend vraiment de votre projet de base.

Dans la page d’édition de mon custom post type

Dans la page d’édition d’un « avis », on retrouve les différents champs ACF.  On peut donc renseigner manuellement une note, en tapant directement un chiffre ou en s’aidant des flèches de navigation qui apparaissent au survol du champ. Petite précision, si vous tapez un chiffre le champ l’acceptera, quelqu’il soit, alors que si on utilise les flèches, on est bien limité de 1 à 5.

post edit acf fields

Attention : pour l’instant il ne faut rien indiquer dans le champs « note », celui-ci est censé se remplir tout seul, grâce à une fonction qui fera la moyenne des trois autres notes.

Créer le système de notation

Dans le fichier pnp de son CPT, on va maintenant appeler nos différents champs ACF, afin d’afficher nos notes.

Tout d’abord, j’appelle le champ « note » qui va contenir ma note globale. C’est le gros 4.5/5, 2.7/5 que vous voyez sur les images plus haut. Pour l’instant il ne doit rien afficher, puisqu’on n’a pas encore rempli ce champ.

<div class="review-score">
<?php
$note = get_field('note');
if($note):
$args = array(
'rating' => $note,
'type' => 'rating',
'number' => '',
);?>
<div>
<span class="note"><?php echo round($note,1) ?>/5</span><span class="average"><?php wp_star_rating( $args ) ?></span></div>
<?php endif;?>
</div>

Ici je ramène la valeur de mon champs avec le get_field (‘note’); Je la mets dans une variable et la passe comme argument de ma fonction wp_star_rating();

D’un côté je veux afficher la valeur du champs, donc une note :

<span class="note"><?php echo round($note,1) ?>/5</span>

J’utilise la fonction round(), avec le 1 pour arrondir à une décimale après la virgule.

De l’autre côté, ou juste à côté plutôt je veux afficher le même résultat mais en icône. J’affiche donc directement la fonction avec mes arguments, wordpress s’occupe du reste. Si ma note est 4.5/5 par exemple, il va appeler 4 icones pleine, puis une à moitié vide.

<span class="average"><?php wp_star_rating( $args ) ?></span>

Ce bout de code sera à terme censé m’afficher ca :

3 champs acf

Ensuite, pour afficher les notes du dessous j’appelle de la même manière les valeurs de mes autres champs:

		<?php if (get_field('animation') || get_field('contenu')  || get_field('organisation') ): ?>

<div class="review-score_features">
<div class="review-score_features_left">
<?php
if(get_field('animation'))
{ $animation = get_field_object('animation');
echo '<div class="review-score_features_left_bloc">' . $animation['label'] .'</div>';
}

if(get_field('contenu'))
{ $contenu = get_field_object('contenu');
echo '<div class="review-score_features_left_bloc">' . $contenu['label'] .'</div>';
}
if(get_field('organisation'))
{ $organisation = get_field_object('organisation');
echo '<div class="review-score_features_left_bloc">' . $organisation['label'] .'</div>';
}
?>
</div>
<div class="review-score_features_right">
<?php

$animation = get_field('animation');
if($animation):
$args = array(
'rating' => $animation,
'type' => 'rating',
'number' => '',
);?>

<div class="review-score_features_right_bloc"><?php wp_star_rating( $args )?></div>
<?php endif;?>

<?php
$contenu = get_field('contenu');
if($contenu):
$args = array(
'rating' => $contenu,
'type' => 'rating',
'number' => '',
);?>

<div class="review-score_features_right_bloc"><?php wp_star_rating( $args )?></div>
<?php endif;?>

<?php
$organisation = get_field('organisation');
if($organisation):
$args = array(
'rating' => $organisation,
'type' => 'rating',
'number' => '',
);?>

<div class="review-score_features_right_bloc"><?php wp_star_rating( $args )?></div>
<?php endif;?>
</div>
</div>
<?php endif;?>

Un get_field() à chaque fois pour récupérer la valeur, et je passe la variable dans les arguments de ma fonction.

Cela est censé m’afficher des icônes comme ci-dessous.

3 champs acf

Si vous utilisez dashicons et les icônes d’étoiles par défaut fourni dans le code css plus haut, vous aurez ici des étoiles à la place des ronds. On va voir plus bas comment mettre ses propres icônes.

Ici, comme le texte utilisé correspond aux titres de mes champs ACF, je peux directement utiliser la fonction get_field_object pour récupérer l’ensemble des attributs de mon champ, et en extraire le titre ou « label« . Ce sont les titres « Animation », « Contenu » et « Organisation » que vous voyez plus haut.

if(get_field('animation'))
{ $animation = get_field_object('animation');
echo '<div class="review-score_features_left_bloc">' . $animation['label'] .'</div>';
}

Dans un widget d’avis, sur lesquels ne figure que la note globale, j’utilise exactement le même code

<div class="review-score">
<?php $note = get_field('note');
if($note){

echo '<div><span class=" note">' . round($note,1) . '/5</span></div>';
}
?>
</div>

Ici il n’y a pas d’étoile ou d’icône, juste la valeur de mon champ « note ».

La fonction de calcul

Maintenant on va voir comment on peut faire en sorte que le champs ACF « note » soit calculé automatiquement.

Pour cela on va devoir insérer une fonction de calcul à l’intérieur du hook ACF ‘acf/save_post‘.

Voici la fonction, à placer dans le fichier functions.php

function my_acf_save_post( $post_id ) {

// get new value
$animation = get_field('animation');
$contenu = get_field('contenu');
$organisation = get_field('organisation');

// do something
$note_globale = $animation + $contenu + $organisation;
$note_finale = $note_globale / 3;
$note = number_format($note_finale,1);
update_field('note', $note, $post_id);
}
add_action('acf/save_post', 'my_acf_save_post', 20);

Comme vous pouvez le voir, c’est assez simple. On récupère la valeur de nos trois champs ACF « Animation », « Contenu » et « Organisation ».

On les additionne et on met la somme dans une variable. Puisque ca doit faire la moyenne de trois note, on divise par trois. On met le résultat dans une nouvelle variable. Cette variable, on la passe dans la fonction number_format

number_format($note_finale,1);

Le 1 sert à limiter à une, le nombre de décimale après la virgule. Pourquoi number_format et pas round() ? Ne me demandez pas, ici round() ne marche tout simplement pas !

Enfin, on utilise la fonction update_field(); pour mettre à jour le champ « note » laissé vide jusque là.

Maintenant une fois que vous aurez rempli les trois champs, Vous pourrez enregistrez votre page à l’édition, rechargez en faisant un Ctrl F5, et le champ affichera la moyenne directement !

Le style personnalisé

Personnellement, dans ce projet, je n’ai pas appelé la bibliothèque dashicons. Puisque je dois afficher des ronds et non des étoiles, je vais devoir trouver une solution personnalisée.

En fait j’utilise les même classes que celles utilisées ou générées par la fonction wp_star_rating( $args ) et j’appelle simplement en background mes images perso.  Les images, soit on les crée soit-même, soit on utilise des images récupérées sur le net, sur flaticon ou tout autre site d’icône.

.star-rating{
display:inline-block;
}
.star-rating .star-full:before {
content: "";
background: url(img/full.png);
display: inline-block;
position: relative;
background-size: 10px;
background-repeat: no-repeat;
width: 10px;
height: 10px;
margin: 0 5px;
}
.star-rating .star-half:before {
content: "";
background: url(img/mid-full.png);
display: inline-block;
position: relative;
background-size: 10px;
background-repeat: no-repeat;
width: 10px;
height: 10px;
margin: 0 5px;
}
.star-rating .star-empty:before {
content: "";
background: url(img/empty.png);
display: inline-block;
position: relative;
background-repeat: no-repeat;
background-size: 10px;
width: 10px;
height: 10px;
margin: 0 5px;
}
.star-rating .star {
display: inline-block;
vertical-align: top;
}

Voilà donc comment intégrer assez simplement un système de notation, plutôt statique, mais qui peut faire son effet !

N’hésitez pas, si vous avez des idées d’amélioration ou des corrections à apporter à ce tuto !