Entity API in Drupal 8

Erstellen eines Custom Entity Types

Walter Jenner, Webentwickler bei Form & Code

(https://slides.com/valderama/entity-api-d8)

Überblick

  • Warum eine Custom Entity?
  • Überblick des nötigen Codes
  • Details anhand eines Beispiels (Demo)
  • Weitere API's

Warum?

  • Optimierte Alternative zu Node Type
  • Nur die Features die man braucht
  • Einfacheres DB Schema

FEATURES

Nodes

 

Revisionable

Translatable

Path Alias

Fieldable

Bundles

 

Vordefinierte Basefields

(sticky, promote)

Custom Entity Type

 

 

 

OPTIONAL

 

 

 

Beliebige Basefields

 

}

DB SCHEMA

Nodes

 

Min. 4 Tabellen

  • node
  • node_revision
  • node_field_data
  • node_field_revision

 

Pro Feld 2 Tabellen

 

 

Custom Entity Type

 

Min. 1 Tabelle 

 

"Map" Feldtyp für serialisierte Daten

Beispiel

  • Datentyp mit 20 Feldern
    • nicht übersetzbar
    • Revisionen nicht nötig
    • alle Felder Single-value und "simple"
  • Node: 4 + 40 = 44 Tabellen
  • Custom Entity: 1 Tabelle mit 20 Spalten

Use Cases D7 contrib

  • Message Entity
  • Product Entity (Commerce)
  • Contact Entity (RedHen CRM)

Ziel: Minimale Custom Entity

  • Eine Datenbank Tabelle
  • Keine konfigurierbaren Bundles
  • "Event"

Wie gehts?

(Grober Überblick)

Klasse die ContentEntityBase erweitert

namespace Drupal\event\Entity;

use Drupal\Core\Entity\ContentEntityBase;

/**
 * @ContentEntityType(
 *   ...  
 * )
 */
class Event extends ContentEntityBase implements EventInterface {

}

modules/event/src/Entity/Event.php

Metadaten per Annotation

Festlegen gewisser Eigenschaften des neuen Entity Types

/**
 * @ContentEntityType(
 *   id = "event",
 *   label = @Translation("Event entity"),
 *   admin_permission = "administer nodes",
 *   base_table = "event",
 *   fieldable = FALSE,
 *   entity_keys = {
 *     "id" = "id",
 *     "label" = "name",
 *     "uuid" = "uuid"
 *   },
 *   handlers = {
 *     "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
 *     "list_builder" = "Drupal\Core\Entity\EntityListBuilder",
 *     "form" = {
 *       "add" = "Drupal\Core\Entity\ContentEntityForm",
 *       "edit" = "Drupal\Core\Entity\ContentEntityForm",
 *       "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm",
 *     },
 *   },
 * )
 */
class Event extends ContentEntityBase implements EventInterface {   }

Beispiel unvollständig! 

Annotation: entity_keys

$event = entity_load('event', 1);

$event->label();
$event->uuid();
$event->id();

// returns the property of the entity which holds it's ID
$event->getEntityKey('id'); 

Um zu definieren welche Felder gewisse Infos der Entity beinhalten:

 entity_keys = {
   "id" = "id",
   "label" = "name", // Entity label is saved in "name" column
   "uuid" = "uuid",
   "bundle" = "event_type"
 },

Anwendung:

Annotation: handlers

handlers = {
 "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
 "list_builder" = "Drupal\event\Entity\Controller\EventListBuilder",
 "views_data" = "Drupal\views\EntityViewsData",
 "form" = {
   "add" = "Drupal\Core\Entity\ContentEntityForm",
   "edit" = "Drupal\Core\Entity\ContentEntityForm",
   "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm",
 },
},

Festlegen welche Klassen gewisse Funktionalität implementieren.

Oft reichen mitgelieferte Standard Entity Klassen.

Felder!

Was braucht unser Entity Type noch?

Felder in D8

  • "Properties" heißen Base Fields
    • ​Single-value und "Simple"
    • Eine Spalte in einer DB Tabelle
    • NEU: Widgets und Formatter
    • NEU: Bei Bedarf übersetzbar
    • NEU: Schema Updates per update.php
  • "Configurable Fields"
    • ​Anlegen per UI
    • Exportierbar mit CMI
    • Eigene Tabelle in der DB
    • (nur innerhalb des Entity Type verwendbar)

baseFieldDefinitions() Methode

class Event extends ContentEntityBase implements EventInterface {

  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
    $fields = [];

    // ID
    $fields['id'] = BaseFieldDefinition::create('integer')
      ->setLabel(t('ID'))
      ->setDescription(t('The ID of the Event entity.'))
      ->setReadOnly(TRUE);

    return $fields;
  }

}
  • Label und Description setzen
  • Feld auf "readonly" setzen
  • Einstellen des Standard Widgets
  • Einstellen des Standard Formatters
  • Änderungen dieser Einstellen per UI verhindern
  • Feld auf required setzen
  • ...

BASE FIELD TYpes

  • string
  • boolean
  • integer
  • decimal
  • float
  • timestamp
  • created
  • changed
  • language
  • date
  • uri
  • uuid
  • email
  • entity_reference
  • path
  • map

Routes

event.routing.yml

entity.event.canonical:
  path: '/event/{event}'
  defaults:
    _entity_view: 'event'
    _title: 'Event'
  requirements:
    _entity_access: 'event.view'
  options:
    _admin_route: TRUE

Working Example

WANT MOAR API?

  • EntityQuery - Weiterentwicklung von EntityFieldQuery
    • Joins
    • OR Conditions!
  • Entity Validation API
    • Formular-unabhängige Validierungskriterien

Danke

Made with Slides.com