Entidades en Drupal 8
DrupalCamp Spain 2017
Luis Ortiz Ramos
CTO de Atenea tech
luis@ateneatech.com
@luisortizramos
Somos expertos en Drupal desde 2007
Somos Siddharta, Oriol, Robert, David, Patricia, Xavi, Rubén y Luis.
Trabajamos para La Vanguardia, Thermomix, Ayuntamiento de Barcelona,
Bodegas Torres, Clínica Dexeus, Amnistía Internacional, Médicos Sin
Fronteras, Infojobs, Estrella Damm, Greenpeace, Chupa Chups, la CUP…
Estamos en Barcelona
Puedes contactar con nosotros en hola@ateneatech.com
Dos tipos de entidades
Configuration entities:
Views, Blocks, Image styles, Menus, Rols…
Forman parte de CMI
Se exportan en archivos Yaml
Content entities
Historia
Drupal 3 y anteriores: solo nodos
Drupal 4: flexinode
Drupal 5: nodos con campos con Content Construction Kit
Drupal 6: nodificamos todo con módulos contribuidos y añadimos campos con
Content Construction Kit
Drupal 7: entidades limitadas en core
Drupal 8: ¡entidades completas en core!
¿Qué es una entidad?
“Entities, in Drupal, are objects that are used for persistent storage of content and
configuration information.”
̶ Entity API
“Loadable thingy, that can optionally be fieldable”
̶ Frando http://dgo.to/460320
Así que… ¿qué es una entidad?
A thingy …
Una unidad de información estructurada:
Un contenido
Un usuario
Un término de un vocabulario
Otra estructura de datos que creemos
… loadable ...
Dispone de un conjunto de funciones para gestionar la información:
Funciones comunes para crear, leer, actualizar y borrar entidades
Propiedades comunes
Integración con Views y otros servicios
… and optionally fieldable
Cada tipo de entidad tiene un conjunto de propiedades.
Cada tipo de entidad puede tener subtipos llamados bundles. Podemos adjuntar
un conjunto de campos diferenciados a cada uno.
Glosario
“contenido” es un tipo de entidad
“artículo” es un tipo de contenido (un bundle)
“Integración Continua y trabajo en equipo en Pantheon” es una entidad
Entidades relevantes en el núcleo de
Drupal 8
Contenido
Cada entidad de este tipo tiene:
ID y UUID
Idioma,
Título
Tipo
Autor
Estado de publicación, promovido a la página de inicio y al principio de las listas
Fecha de creación y del último cambio
Usuario
Cada entidad de este tipo tiene:
ID y UUID
Idioma
Nombre
Clave
Correo electrónico
Idioma predefinido y idioma predefinido de administración
Zona horaria
Bloques personalizados
Cada entidad de este tipo tiene:
ID y UUID
Idioma
Info
Tipo
Fecha de creación
Información de la última revisión
Término
Cada entidad de este tipo tiene:
ID y UUID
Idioma
Nombre
Vocabulario
Descripción
Término padre
Peso
Comentario
Cada entidad de este tipo tiene:
ID y UUID
Idioma
Tipo
Asunto
Comentario padre
Entidad que se comenta y campo
Autor
Archivos
Cada entidad de este tipo tiene:
ID y UUID
Idioma
Nombre del archivo
Usuario del archivo
URI
Tipo MIME
Tamaño del archivo
Trabajando con entidades
Acceso a entidades
$manager = Drupal::entityTypeManager();
$entity = $manager
->getStorage('comment')
->load($id);
$entity = Comment::load($id);
$user = User::create(array('name' => 'me'));
$entity->getEntityTypeId();
$entity->label();
$entity->id();
Acceso a campos
echo $entity->subject->value;
$term_id = $entity
->field_tags[2]
->target_id;
$entity->hasField($field_name);
$entity = $field_item->getEntity();
$entity->title->value = 'new Title';
$entity->save();
if ($node->isPromoted()) {
$title = $node->getTitle();
} elseif ($node->isPublished()) {
$node->setTitle(
$node->getAuthor()
->getUsername()
);
}
Acceso a traducciones
echo $entity
->getTranslation('de')
->title->value;
$translation = $entity->getTranslation('de');
$translation->language()->id == 'de';
$translation->title->value = 'German title';
$translation = $manager
->getTranslationFromContext($entity);
echo $translation->label();
$entity = $translation->getUntranslated();
Acceso a definiciones
echo $entity
->getTranslation('de')
->title->value;
$translation = $entity->getTranslation('de');
$translation->language()->id == 'de';
$translation->title->value = 'German title';
$translation = $manager
->getTranslationFromContext($entity);
echo $translation->label();
$entity = $translation->getUntranslated();
Acceso a definiciones
$entity_type = $entity_manager
->getDefinition('node');
$entity_type->id() == 'node'
$entity_type
->getClass()
$entity_type
->hasKey('label')
$entity_type
->isSubclassOf('ContentEntityInterface')
$field_definition = $entity->
getFieldDefinition($field_name);
$field_definition->getName();
$field_definition->getPropertyDefinitions();
$entity_manager
->getFieldDefinitions('node', 'article');
Tipos de entidad personalizados
Son plugins
Deben estar en Drupal/module/Entity
Deben cumplir la anotación @ContentEntityType
Deben implementar ContentEntityBase
/**
* Defines the comment entity class.
*
* @ContentEntityType(
* id = "comment",
* label = @Translation("Comment"),
* bundle_label = @Translation("Comment type"),
...
...
* handlers = {
* "storage" = "DrupalcommentCommentStorage",
* "storage_schema" = "DrupalcommentCommentStorageSchema",
* "access" = "DrupalcommentCommentAccessControlHandler",
* "list_builder" = "DrupalCoreEntityEntityListBuilder",
* "view_builder" = "DrupalcommentCommentViewBuilder",
* "views_data" = "DrupalcommentCommentViewsData",
* "form" = {
* "default" = "DrupalcommentCommentForm",
* "delete" = "DrupalcommentFormDeleteForm"
* },
* "translation" = “DrupalcommentCommentTranslationHandler"
* },
...
...
* base_table = "comment",
* data_table = "comment_field_data",
* uri_callback = "comment_uri",
* translatable = TRUE,
* entity_keys = {
* "id" = "cid",
* "bundle" = "comment_type",
* "label" = "subject",
* "langcode" = "langcode",
* "uuid" = "uuid"
* },
...
...
* links = {
* "canonical" = "/comment/{comment}",
* "delete-form" = "/comment/{comment}/delete",
* "edit-form" = "/comment/{comment}/edit",
* },
* bundle_entity_type = "comment_type",
* field_ui_base_route = "entity.comment_type.edit_form",
* constraints = {
* "CommentName" = {}
* }
* )
*/
Definen sus campos base
Implementan la función baseFieldDefinitions
Usan BaseFieldDefinition::create para añadir campos:
Tipo de campo
Propiedades
Formateadores
...
public static function baseFieldDefinitions(EntityTypeInterface
$entity_type) {
$fields = parent::baseFieldDefinitions($entity_type);
$fields['subject'] = BaseFieldDefinition::create('string')
->setLabel(t('Subject'))
->setTranslatable(TRUE)
->setSetting('max_length', 64)
->setDisplayOptions('form', array(
'type' => 'string_textfield',
'weight' => 10,
))
->setDisplayConfigurable('form', TRUE);
return $fields;
}
...
...
$fields['title'] = FieldDefinition::create('string')
->setLabel(t('Title'))
...
->setDisplayOptions('view', array(
'label' => 'hidden',
'type' => 'string',
'weight' => -5,
))
->setDisplayOptions('form', array(
'type' => 'string',
'weight' => -5,
))
->setDisplayConfigurable('form', TRUE);
...
Implementan handlers
Son clases independientes del tipo de entidad
Definen:
Storage
Access
List and view builder
Views data
Forms
...
* handlers = {
* "storage" = "DrupalcommentCommentStorage",
* "storage_schema" = "DrupalcommentCommentStorageSchema",
* "access" = "DrupalcommentCommentAccessControlHandler",
* "list_builder" = "DrupalCoreEntityEntityListBuilder",
* "view_builder" = "DrupalcommentCommentViewBuilder",
* "views_data" = "DrupalcommentCommentViewsData",
* "form" = {
* "default" = "DrupalcommentCommentForm",
* "delete" = "DrupalcommentFormDeleteForm"
* },
* "translation" =
“DrupalcommentCommentTranslationHandler"
* },
...
Handler de ejemplo: Storage
Se utiliza para gestionar la persistencia de la entidad.
Implementa EntityStorageInterface
Implementaciones base:
SqlContentEntityStorage
ContentEntityNullStorage
class CommentStorage extends SqlContentEntityStorage implements
CommentStorageInterface {
...
public function loadThread(...) {
...
}
...
}
Entity keys
Definen las claves que se usarán para cargar las entidades
ContentEntityBase::baseFieldDefinitions crea campos para ellas automáticamente
...
* entity_keys = {
* "id" = "cid",
* "bundle" = "comment_type",
* "label" = "subject",
* "langcode" = "langcode",
* "uuid" = "uuid"
* },
...
Links
Define la forma de los enlaces:
canonical
add-form
edit-form
delete-form
...
...
* links = {
* "canonical" = "/comment/{comment}",
* "delete-form" = "/comment/{comment}/delete",
* "edit-form" = "/comment/{comment}/edit",
* },
...
Routing
Se debe implementar el routing de los enlaces
Dos formas:
Es posible definir las rutas en el archivo *.routing.yml
Es mejor usar un handler route_provider como DefaultHtmlRouteProvider
¿Por qué crear nuevos tipos de
entidades?
Cuando necesitas un tipo de entidad específico: propiedades, métodos, acceso,
almacenamiento…
Cuando no quieres usar un tipo existente: puedes clonar uno y los demás
módulos no sabrán de él
Cuando necesitas control total sobre él: los campos base no pueden
modificarse usando la interfaz
Cuando el modelo de datos es muy complicado: como pasa con Commerce,
Flag o Paragraphs
Modificar tipos de entidades existentes
Entity API
Funciones para alterar:
Campos base, de bundle y extras
Control de acceso
CRUD
Visualización
Formularios
https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21enti
¡Gracias!
¿Preguntas?

Entidades en drupal 8

  • 1.
    Entidades en Drupal8 DrupalCamp Spain 2017
  • 2.
    Luis Ortiz Ramos CTOde Atenea tech luis@ateneatech.com @luisortizramos
  • 4.
    Somos expertos enDrupal desde 2007 Somos Siddharta, Oriol, Robert, David, Patricia, Xavi, Rubén y Luis. Trabajamos para La Vanguardia, Thermomix, Ayuntamiento de Barcelona, Bodegas Torres, Clínica Dexeus, Amnistía Internacional, Médicos Sin Fronteras, Infojobs, Estrella Damm, Greenpeace, Chupa Chups, la CUP… Estamos en Barcelona Puedes contactar con nosotros en hola@ateneatech.com
  • 6.
    Dos tipos deentidades
  • 7.
    Configuration entities: Views, Blocks,Image styles, Menus, Rols… Forman parte de CMI Se exportan en archivos Yaml Content entities
  • 8.
  • 9.
    Drupal 3 yanteriores: solo nodos Drupal 4: flexinode Drupal 5: nodos con campos con Content Construction Kit Drupal 6: nodificamos todo con módulos contribuidos y añadimos campos con Content Construction Kit Drupal 7: entidades limitadas en core Drupal 8: ¡entidades completas en core!
  • 10.
    ¿Qué es unaentidad?
  • 11.
    “Entities, in Drupal,are objects that are used for persistent storage of content and configuration information.” ̶ Entity API
  • 12.
    “Loadable thingy, thatcan optionally be fieldable” ̶ Frando http://dgo.to/460320
  • 13.
    Así que… ¿quées una entidad?
  • 14.
    A thingy … Unaunidad de información estructurada: Un contenido Un usuario Un término de un vocabulario Otra estructura de datos que creemos
  • 15.
    … loadable ... Disponede un conjunto de funciones para gestionar la información: Funciones comunes para crear, leer, actualizar y borrar entidades Propiedades comunes Integración con Views y otros servicios
  • 16.
    … and optionallyfieldable Cada tipo de entidad tiene un conjunto de propiedades. Cada tipo de entidad puede tener subtipos llamados bundles. Podemos adjuntar un conjunto de campos diferenciados a cada uno.
  • 17.
  • 18.
    “contenido” es untipo de entidad “artículo” es un tipo de contenido (un bundle) “Integración Continua y trabajo en equipo en Pantheon” es una entidad
  • 19.
    Entidades relevantes enel núcleo de Drupal 8
  • 20.
    Contenido Cada entidad deeste tipo tiene: ID y UUID Idioma, Título Tipo Autor Estado de publicación, promovido a la página de inicio y al principio de las listas Fecha de creación y del último cambio
  • 21.
    Usuario Cada entidad deeste tipo tiene: ID y UUID Idioma Nombre Clave Correo electrónico Idioma predefinido y idioma predefinido de administración Zona horaria
  • 22.
    Bloques personalizados Cada entidadde este tipo tiene: ID y UUID Idioma Info Tipo Fecha de creación Información de la última revisión
  • 23.
    Término Cada entidad deeste tipo tiene: ID y UUID Idioma Nombre Vocabulario Descripción Término padre Peso
  • 24.
    Comentario Cada entidad deeste tipo tiene: ID y UUID Idioma Tipo Asunto Comentario padre Entidad que se comenta y campo Autor
  • 25.
    Archivos Cada entidad deeste tipo tiene: ID y UUID Idioma Nombre del archivo Usuario del archivo URI Tipo MIME Tamaño del archivo
  • 26.
  • 27.
  • 28.
    $manager = Drupal::entityTypeManager(); $entity= $manager ->getStorage('comment') ->load($id); $entity = Comment::load($id); $user = User::create(array('name' => 'me')); $entity->getEntityTypeId(); $entity->label(); $entity->id();
  • 29.
  • 30.
    echo $entity->subject->value; $term_id =$entity ->field_tags[2] ->target_id; $entity->hasField($field_name); $entity = $field_item->getEntity(); $entity->title->value = 'new Title'; $entity->save();
  • 31.
    if ($node->isPromoted()) { $title= $node->getTitle(); } elseif ($node->isPublished()) { $node->setTitle( $node->getAuthor() ->getUsername() ); }
  • 32.
  • 33.
    echo $entity ->getTranslation('de') ->title->value; $translation =$entity->getTranslation('de'); $translation->language()->id == 'de'; $translation->title->value = 'German title'; $translation = $manager ->getTranslationFromContext($entity); echo $translation->label(); $entity = $translation->getUntranslated();
  • 34.
  • 35.
    echo $entity ->getTranslation('de') ->title->value; $translation =$entity->getTranslation('de'); $translation->language()->id == 'de'; $translation->title->value = 'German title'; $translation = $manager ->getTranslationFromContext($entity); echo $translation->label(); $entity = $translation->getUntranslated();
  • 36.
  • 37.
    $entity_type = $entity_manager ->getDefinition('node'); $entity_type->id()== 'node' $entity_type ->getClass() $entity_type ->hasKey('label') $entity_type ->isSubclassOf('ContentEntityInterface')
  • 38.
  • 39.
    Tipos de entidadpersonalizados
  • 40.
    Son plugins Deben estaren Drupal/module/Entity Deben cumplir la anotación @ContentEntityType Deben implementar ContentEntityBase
  • 41.
    /** * Defines thecomment entity class. * * @ContentEntityType( * id = "comment", * label = @Translation("Comment"), * bundle_label = @Translation("Comment type"), ...
  • 42.
    ... * handlers ={ * "storage" = "DrupalcommentCommentStorage", * "storage_schema" = "DrupalcommentCommentStorageSchema", * "access" = "DrupalcommentCommentAccessControlHandler", * "list_builder" = "DrupalCoreEntityEntityListBuilder", * "view_builder" = "DrupalcommentCommentViewBuilder", * "views_data" = "DrupalcommentCommentViewsData", * "form" = { * "default" = "DrupalcommentCommentForm", * "delete" = "DrupalcommentFormDeleteForm" * }, * "translation" = “DrupalcommentCommentTranslationHandler" * }, ...
  • 43.
    ... * base_table ="comment", * data_table = "comment_field_data", * uri_callback = "comment_uri", * translatable = TRUE, * entity_keys = { * "id" = "cid", * "bundle" = "comment_type", * "label" = "subject", * "langcode" = "langcode", * "uuid" = "uuid" * }, ...
  • 44.
    ... * links ={ * "canonical" = "/comment/{comment}", * "delete-form" = "/comment/{comment}/delete", * "edit-form" = "/comment/{comment}/edit", * }, * bundle_entity_type = "comment_type", * field_ui_base_route = "entity.comment_type.edit_form", * constraints = { * "CommentName" = {} * } * ) */
  • 45.
    Definen sus camposbase Implementan la función baseFieldDefinitions Usan BaseFieldDefinition::create para añadir campos: Tipo de campo Propiedades Formateadores
  • 46.
    ... public static functionbaseFieldDefinitions(EntityTypeInterface $entity_type) { $fields = parent::baseFieldDefinitions($entity_type); $fields['subject'] = BaseFieldDefinition::create('string') ->setLabel(t('Subject')) ->setTranslatable(TRUE) ->setSetting('max_length', 64) ->setDisplayOptions('form', array( 'type' => 'string_textfield', 'weight' => 10, )) ->setDisplayConfigurable('form', TRUE); return $fields; } ...
  • 47.
    ... $fields['title'] = FieldDefinition::create('string') ->setLabel(t('Title')) ... ->setDisplayOptions('view',array( 'label' => 'hidden', 'type' => 'string', 'weight' => -5, )) ->setDisplayOptions('form', array( 'type' => 'string', 'weight' => -5, )) ->setDisplayConfigurable('form', TRUE); ...
  • 48.
    Implementan handlers Son clasesindependientes del tipo de entidad Definen: Storage Access List and view builder Views data Forms
  • 49.
    ... * handlers ={ * "storage" = "DrupalcommentCommentStorage", * "storage_schema" = "DrupalcommentCommentStorageSchema", * "access" = "DrupalcommentCommentAccessControlHandler", * "list_builder" = "DrupalCoreEntityEntityListBuilder", * "view_builder" = "DrupalcommentCommentViewBuilder", * "views_data" = "DrupalcommentCommentViewsData", * "form" = { * "default" = "DrupalcommentCommentForm", * "delete" = "DrupalcommentFormDeleteForm" * }, * "translation" = “DrupalcommentCommentTranslationHandler" * }, ...
  • 50.
    Handler de ejemplo:Storage Se utiliza para gestionar la persistencia de la entidad. Implementa EntityStorageInterface Implementaciones base: SqlContentEntityStorage ContentEntityNullStorage
  • 51.
    class CommentStorage extendsSqlContentEntityStorage implements CommentStorageInterface { ... public function loadThread(...) { ... } ... }
  • 52.
    Entity keys Definen lasclaves que se usarán para cargar las entidades ContentEntityBase::baseFieldDefinitions crea campos para ellas automáticamente
  • 53.
    ... * entity_keys ={ * "id" = "cid", * "bundle" = "comment_type", * "label" = "subject", * "langcode" = "langcode", * "uuid" = "uuid" * }, ...
  • 54.
    Links Define la formade los enlaces: canonical add-form edit-form delete-form ...
  • 55.
    ... * links ={ * "canonical" = "/comment/{comment}", * "delete-form" = "/comment/{comment}/delete", * "edit-form" = "/comment/{comment}/edit", * }, ...
  • 56.
    Routing Se debe implementarel routing de los enlaces Dos formas: Es posible definir las rutas en el archivo *.routing.yml Es mejor usar un handler route_provider como DefaultHtmlRouteProvider
  • 57.
    ¿Por qué crearnuevos tipos de entidades?
  • 58.
    Cuando necesitas untipo de entidad específico: propiedades, métodos, acceso, almacenamiento… Cuando no quieres usar un tipo existente: puedes clonar uno y los demás módulos no sabrán de él Cuando necesitas control total sobre él: los campos base no pueden modificarse usando la interfaz Cuando el modelo de datos es muy complicado: como pasa con Commerce, Flag o Paragraphs
  • 59.
    Modificar tipos deentidades existentes
  • 60.
    Entity API Funciones paraalterar: Campos base, de bundle y extras Control de acceso CRUD Visualización Formularios https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21enti
  • 61.