Explorer les Livres électroniques
Catégories
Explorer les Livres audio
Catégories
Explorer les Magazines
Catégories
Explorer les Documents
Catégories
chrono
Dans un précédent billet, nous avons découvert le projet Console qui permet d'automatiser la création de
modules Drupal 8 et d'autres taches récurrentes. Découvrons ensemble quelques autres fonctionnalités très
intéressantes.
Les entités sont au coeur de l'architecture Drupal, et encore plus dans Drupal 8 où tout (ou presque) est une
entité. Les Noeuds, Users, Termes de taxonomies (pour ne citer que les plus connues) de Drupal sont des
entités. Créer une nouvelle entité peut permettre de répondre à des fonctionnalités spécifiques en
implémentant au sein de celle-ci sa propre logique métier, et / ou encore de répondre à une problématique de
performance en implémentant dans la table de base de l'entité toutes ses propriétés métier, évitant ainsi de
nombreuses et coûteuses requêtes pour générer et rendre une (ou plusieurs dizaines de milliers) instance de
cette entité.
cd /path/to/drupal8folder
bin/console generate:entity:content
Nous déclarons notre nouvelle entité dans notre prédécent module créé, intitulé Example, et donnons un
nom à notre entité et sa classe.
En 3 questions, et moins de 10 secondes, nous venons de générer tout le code pour implémenter une
nouvelle entité.
Outre avoir mis à jour le fichier de déclaration des routes (example.routing.yml) et les fichiers de lien
(example.links.menu.yml, etc), la commande a généré les fichiers suivants :
Nous pouvons ajouter autant de champs que nécessaire à notre nouvelle entité et également gérer l'affichage
du formulaire et/ou celui du rendu depuis les onglets correspondants.
Nous pouvons consulter, créer, modifier ou supprimer nos entités depuis les chemins fournis par défaut, que
nous pouvons bien sûr modifier depuis le fichier example.routing.yml
Bref nous disposons désormais de notre propre entité qui bénéficie de base de toute la puissance de Drupal 8
au travers de son API, notamment la field API et la form API.
Dans notre fichier Note.php généré par Console, ajoutons cette ligne
"views_data" = "Drupal\example\Entity\NoteViewsData",
/**
* @file
* Contains Drupal\example\Entity\Note.
*/
namespace Drupal\example\Entity;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\example\NoteInterface;
use Drupal\user\UserInterface;
/**
* Defines the Note entity.
*
* @ingroup example
*
* @ContentEntityType(
* id = "note",
* label = @Translation("Note entity"),
* handlers = {
* "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
* "list_builder" = "Drupal\example\Entity\Controller\NoteListController",
* "views_data" = "Drupal\example\Entity\NoteViewsData",
*
* "form" = {
* "add" = "Drupal\example\Entity\Form\NoteForm",
* "edit" = "Drupal\example\Entity\Form\NoteForm",
* "delete" = "Drupal\example\Entity\Form\NoteDeleteForm",
* },
* "access" = "Drupal\example\NoteAccessControlHandler",
* },
* base_table = "note",
* admin_permission = "administer Note entity",
* fieldable = TRUE,
* entity_keys = {
* "id" = "id",
* "label" = "name",
* "uuid" = "uuid"
* },
* links = {
* "edit-form" = "note.edit",
* "admin-form" = "note.settings",
* "delete-form" = "note.delete"
* },
* field_ui_base_route = "note.settings"
* )
*/
/**
* @file
* Contains Drupal\example\Entity\NoteViewsData.
*/
namespace Drupal\example\Entity;
use Drupal\views\EntityViewsData;
use Drupal\views\EntityViewsDataInterface;
/**
* Provides the views data for the node entity type.
*/
class NoteViewsData extends EntityViewsData implements EntityViewsDataInterface {
/**
* {@inheritdoc}
*/
public function getViewsData() {
$data = parent::getViewsData();
$data['note']['table']['base'] = array(
'field' => 'id',
'title' => t('Note'),
'help' => t('The note entity ID.'),
);
return $data;
}
}
Notre entité est alors disponible en tant que telle dans Views. Ainsi que tous les champs qui lui seront
ajoutés (dans l'exemple ci-dessous un champ décimal intitulé Note a été rajouté à notre entité)
Pour finir l'intégration complète de notre entité avec Views, et pouvoir par exemple utiliser le mode de
rendu de notre entité pour l'affichage de la vue, il nous faut fournir un template à notre entité. Nous allons
donc modifier notre fichier example.module pour implémenter la fonction hook_theme.
/**
* Implements hook_theme().
*/
function example_theme()
{
$theme = [];
$theme['note'] = array(
'render element' => 'elements',
'file' => 'note.page.inc',
'template' => 'note',
);
return $theme;
}
Nous implémentons avec cette fonction le template note.html.twig et nous utilisons le fichier note.page.inc
pour fournir les variables à notre template. Créons nos deux fichiers, note.html.twig dans le répertoire
template de notre module, et note.page.inc à la racine.
{#
/**
* @file note.html.twig
* Default theme implementation to present note data.
*
* This template is used when viewing a note entity's page,
*
*
* Available variables:
* - content: A list of content items. Use 'content' to print all content, or
* - attributes: HTML attributes for the container element.
*
* @see template_preprocess_note()
*
* @ingroup themeable
*/
#}
<div {{ attributes.addClass("note") }}>
{% if content %}
{{- content -}}
{% endif %}
</div>
Et le fichier note.page.inc
/**
* @file note.page.inc
* Note page callback file for the note entity.
*/
use Drupal\Core\Render\Element;
/**
* Prepares variables for note templates.
*
* Default template: note.html.twig.
*
* @param array $variables
* An associative array containing:
* - elements: An associative array containing the user information and any
* - attributes: HTML attributes for the containing element.
*/
function template_preprocess_note(&$variables) {
Ajoutons à notre entité trois propriétés : une note littérale, une appréciation littérale et enfin l'élève (sous la
forme d'un champ Entity Reference ciblant les utilisateurs enregistrés). Pour ce nous les déclarons dans la
fonction baseFieldDefinitions de notre fichier Note.php implémentant la classe de notre entité.
/**
* {@inheritdoc}
*/
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields['id'] = BaseFieldDefinition::create('integer')
->setLabel(t('ID'))
->setDescription(t('The ID of the Note entity.'))
->setReadOnly(TRUE);
$fields['uuid'] = BaseFieldDefinition::create('uuid')
->setLabel(t('UUID'))
->setDescription(t('The UUID of the Note entity.'))
->setReadOnly(TRUE);
$fields['name'] = BaseFieldDefinition::create('string')
->setLabel(t('Name'))
->setDescription(t('The name of the Note entity.'))
->setSettings(array(
'default_value' => '',
'max_length' => 50,
'text_processing' => 0,
))
->setDisplayOptions('view', array(
'label' => 'above',
'type' => 'string',
'weight' => -4,
))
->setDisplayOptions('form', array(
'type' => 'string',
'weight' => -4,
))
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
// Student ID field.
// Entity reference field, holds the reference to the user object.
// The view shows the user name field of the user.
// The form presents a auto complete field for the user name.
$fields['user_id'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Student Name'))
->setDescription(t('The Name of the student.'))
->setSetting('target_type', 'user')
->setSetting('handler', 'default')
->setDisplayOptions('view', array(
'label' => 'above',
'type' => 'entity_reference',
'weight' => -3,
))
->setDisplayOptions('form', array(
'type' => 'entity_reference_autocomplete',
'settings' => array(
'match_operator' => 'CONTAINS',
'size' => 60,
'autocomplete_type' => 'tags',
'placeholder' => '',
),
'weight' => -3,
))
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['langcode'] = BaseFieldDefinition::create('language')
->setLabel(t('Language code'))
->setDescription(t('The language code of Note entity.'));
$fields['created'] = BaseFieldDefinition::create('created')
->setLabel(t('Created'))
->setDescription(t('The time that the entity was created.'));
$fields['changed'] = BaseFieldDefinition::create('changed')
->setLabel(t('Changed'))
->setDescription(t('The time that the entity was last edited.'));
return $fields;
}
Ces 3 propriétés seront configurables dans le formulaire de création et le rendu de l'entité grâce aux options
setDisplayConfigurable('form', TRUE) et setDisplayConfigurable('view', TRUE).
Drupal fournit de base les types de champs suivants. En complément, les modules peuvent fournir d'autres
types de champs qui peuvent alors être utilisés également.
Pour activer ces trois nouveaux champs, il faut bien sûr désinstaller / réinstaller notre module s'il était déjà
activé, afin de relancer le processus de création de notre entité, et que nos nouveaux champs soient créés au
niveau de la table de base de l'entité.
Notre table contient désormais bien nos nouveaux champs.
Et nous pouvons bien sûr paramétrer notre formulaire de saisie au moyen de l'interface, aussi bien que le
rendu de notre entité depuis l'onglet Manage Display ou Gérer l'Affichage si vous avez choisi le français lors
de l'installation de Drupal 8.
Nous disposons alors d'une entité sur mesure, dont les champs spécifiques sont stockés dans la même table
de la base de données et bien sûr accessibles depuis Views.
Il ne restera plus, au niveau de l'intégration de notre entité dans Views, qu'à faire la jointure entre le champ
spécifique Student Name et la table des utilisateurs pour pouvoir récupérer toutes leurs informations, si
nécessaire.
En guise de conclusion
Le module Console nous permet à la fois de gagner du temps et de disposer d'une base solide et saine pour
commencer à implémenter des propriétés ou des logiques métier. Et de par sa nouvelle API et son approche
objet, Drupal 8 semble encore plus redoutable que son prédécesseur, pourtant déjà bien armé, et donne
encore plus de sens à cette maxime.
Au final, cela nous aura pris peut-être un peu plus que 10 secondes, mais pas pour la génération de notre
entité brute. Nous sommes d'accord ?