D8 Entity API - pierregermain/MyDrupal GitHub Wiki

Ir a Entidades de contenido

Introducción

Tipos de Entidades

  • Configuration Entity:
    • No tienen campos
    • Usan el sistema de configuración para almacenar los datos (similar a configuracion API)
  • Content Entity

Diagrama de tipo de Entidades

Listar entidades con drupal console

drupal de

Tipo Entidad (Entity Type)

  • Directorio: /src/Entity
  • Annotation: @EntityType

Bundles

  • entidad node tiene bundles article, page.
  • entidad user no tiene bundles

Operaciones CRUD sobre Entity API

Comprobación del Objeto Entity

Primero averiguamos que tipo de objeto es la entidad:

// Comprueba si es una entidad
if ($entity instanceof \Drupal\Core\Entity\EntityInterface) {...}

// Comprueba si es una entidad de contenido
if ($entity instanceof \Drupal\Core\Entity\ContentEntityInterface) {...}

// Comprueba si es una entidad de configuración
if ($entity instanceof \Drupal\Core\Config\Entity\ConfigEntityInterface) {...}

// Comprueba si es una entidad de tipo Node
if ($entity instanceof \Drupal\node\NodeInterface) {...}

Después obtenemos el tipo de entidad:

// Obtener el tipo de entidad
$entity->getEntityTypeId();

Obtener Información de entidades

En EntityInterface se obtiene toda la información de la entidad

// Obtiene el ID de la entidad
$entity->id();

// Otiene el UUID (identificador único) de la entidad
$entity->uuid();

// Obtiene el bundle (subtipo) de la entidad
$entity->bundle();

// Comprueba si la entidad es nueva (se está creando)
$entity->isNew();

// Obtiene la etiqueta de la entidad.
$entity->label();

// Obtiene un array con todas las propiedades de la entidad
$entity->toArray();

// Obtiene el objeto URL que apunta a la entidad
$entity->toUrl();

// Obtiene el enlace HTML que apunta a la entidad
$entity->toLink();

EntityTypeManager y almacén de entidades

  • Permite gestionar entidades.
  • Servicio: entity_type.manager
  • Clase: EntityTypeManager

Es importante entender que para poder hacer operaciones sobre entidadades necesitamos usar el EntityTypeManager para acceder al almacén que implemente EntityStorageInterface que es con el que podemos hacer operaciones CRUD.

$node_storage = \Drupal::entityTypeManager()->getStorage('node');
$user_storage = \Drupal::entityTypeManager()->getStorage('user');

Carga de Entidades

load($id)

// Carga entidad por ID
$node = $node_storage->load(1);

loadMultiple(array $ids)

// Carga por varios nids
$selected_users = [4, 13, 27];
$accounts = $user_storage->loadMultiple($selected_users);

loadByProperties(array $values)

// Carga de usuario buscando por propiedades
$accounts = $user_storage->loadByProperties(['name' => $username,
'status' => 1]);

hook_ENTITY_TYPE_load($entities)

Hook que se puede usar al cargar una entidad en drupal

Crear y actualizar entidades

create(array $values)

// Creación de un nodo con propiedades sin guardarlo
$node = $node_storage->create([
  'type' => 'article',
  'title' => 'Sample node'
]);

// Creación de un usuario con propiedades sin guardarlo
$new_user = $user_storage->create([
  'name' => 'test_user',
  'mail' => '[email protected]',
  'pass' => '123456',
]);

save($entity)

// Guardar una entidad. Si ya existe la sobreescribe
$new_user->save();

// Forzar que la entidad se creé cómo nueva (por ejemplo al importar datos a la DB):
$entity->enforceIsNew(),

Ejemplo update de campo solr exclude (el field se llama sae_exclude)

/**
 * Implements hook_cron().
 *
 * Remove Past events from solr
 *
 */
function custom_search_api_exclude_cron() {

  $now = new DrupalDateTime('now -1 day');

  // Obtener nodos con solr exlude a 0
  $query = \Drupal::entityQuery('node')
    ->condition('status', 1)
    ->condition('type', 'events')
    ->condition('sae_exclude',0 ,'=')
    ->condition('field_event_date', $now->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT), '<');

  $entity_ids = $query->execute();

  $node_storage = \Drupal::entityTypeManager()->getStorage('node');
  // Poner solr exlude a 1
  foreach ($entity_ids as $nid) {
    $node = $node_storage->load($nid);
    $node->sae_exclude = 1;
    $node->save();
  }

}

Hooks al crear entidades (create, presave, insert y update)

hook_ENTITY_TYPE_create($entity)

Hook que se ejecuta al crear una entidad. OJO: Este hook se ejecuta al crear una entidad, es decir no tendrá ningún dato aún.

Ejemplo para node:

/**
 * Implements hook_ENTITY_TYPE_create() for node.
 */
function mymodule_node_create(\Drupal\Core\Entity\EntityInterface $entity) {
  \Drupal::logger('mymodule')->info('Node created');
}

Ejemplo para user:

/**
 * Implements hook_ENTITY_TYPE_create() for user.
 */
function mymodule_user_create(EntityInterface $entity) {
  \Drupal::logger('mymodule')->info('User created');
}

Otros hooks al crear una entidad (presave, insert, update)

  • hook_ENTITY_TYPE_presave($entity): Actúa antes de que la entidad sea creada o actualizada.
  • hook_ENTITY_TYPE_insert($entity): Actúa cuando la nueva entidad ha sido almacenada.
  • hook_ENTITY_TYPE_update($entity): Actúa cuando se actualiza una entidad existente
/**
 * Implements hook_ENTITY_TYPE_insert() for user.
 */
function mymodule_user_insert(EntityInterface $entity) {
  if($entity instanceof User){
    createPage($entity->id(), $entity->getUsername());
  }
}
function createPage($uid, $name) {
  $node_storage = \Drupal::entityTypeManager()->getStorage('node');
  $node = $node_storage->create([
    'type' => 'page',
    'title' => t('Presentation of') . ' ' . $name,
    'uid' => $uid,
  ]);
  $node->save();
}

Eliminar entidades

2 formas de borrar entidades

delete(array $entities): Método del almacén de entidades

$node_storage->delete([$id1 => $entity1, $id2 => $entity2]);

delete(): Método de la entidad

$entity->delete();

Borrado con Entity Query

$query = \Drupal::entityQuery('my_custom_table')->condition('custom_field', $entity->id());
$entity_ids = $query->execute();
$storage = \Drupal::entityTypeManager()->getStorage('my_custom_table');
$storage->delete($storage->loadMultiple($entity_ids));

Hooks al eliminar entidades

  • hook_ENTITY_TYPE_predelete($entity): Actúa antes de que se borre la entidad
  • hook_ENTITY_TYPE_delete($entity): Actúa una vez que se haya borrado la entidad. Se usa para borrar información relacionada con la entidad borrada.

Control de accesso a entidades

Método access de la entidad.

Entity::access($operation, AccountInterface $account = NULL, $return_as_object = FALSE)

  • $operation. Indicamos la operación a evaluar: 'create', 'view', 'edit', 'delete'.
  • $account. Si no se indica una cuenta de usuario, se evaluará sobre el usuario actual.

Más info aquí

if ($entity->access('view')) {
}

Otra forma

Cuando no hay una entidad disponible podemos usar entityTypeManager:

$access_control_handler = \Drupal::entityTypeManager()->getAccessControlHandler('node');

if (($account->hasPermission('add content to books') &&
  $access_control_handler->createAccess('book'){
}

Acceso a valores de campos de entidades

  • Podemos usar el siguiente método para acceder a los valores de una entidad.
  • El valor devuelvto es siempre un array
$entity->get("FIELD")->getValue();

Ejemplo:

$body = $node->get('body')->getValue();
dpm($body);

Para acceder a los valores devueltos en el array usaremos:

// valor del campo
$body[0]['value'];
// resumen
$body[0]['summary'];
// formato
$body[0]['format'];

Para acceder a taxonomía de un nodo usamos lo siguiente

$terms = $node->get('field_tags')->getValue();
$term_storage = \Drupal::entityTypeManager()->getStorage('taxonomy_term');

foreach($terms as $term_id) {
  $term = $term_storage->load($term_id['target_id']);
  dpm($term->label());
}

Acceso a entidades con entityQuery

  • formato similar a consultas contra la db
$query = \Drupal::entityQuery('node')
  ->condition('status', 1)
  ->condition('type', 'article')
  ->range(0,5)
  ->sort('changed', 'DESC');
$entity_ids = $query->execute();
  • Uso de date fields
$now = new DrupalDateTime('now');
$query = \Drupal::entityQuery('node');
$query->condition('field_date', $now->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT), '>=');
$results = $query->execute();

Entidades de configuración

Más info

Se recomienda usar Drupal Console para generar el esqueleto de la entidad.

drupal generate:entity:config

 // Welcome to the Drupal Config Entity generator
 Enter the module name [admin_toolbar]:
 > mymodule_entities 


 Enter the class of your new config entity [DefaultEntity]:
 > SectionEntity

 Enter the name of your new config entity [section_entity]:
 > mymodule_section

 Enter the label of your new config entity [Section entity]:
 > 

 Enter the base-path for the config entity routes [/admin/structure]:
 > 

Esto nos crea un enlace en /admin/structure/mymodule_section

  • En dicha ruta se podrán visualizar las entidades creadas.
  • Al añádir una nos pide rellenar el campo "label" de tipo machine_name.
  • Una vez añadido nos regresa al listado de entidades.

Ejemplo:

  • Cómo ejemplo vamos a ver cómo se modificaría una entidad de configuración que tendrá cómo propiedad adicional "color".

Partes que hay que implementar para crear una entidad:

  1. Clases del tipo de entidad
  • src/Entity/SectionEntityInterface.php
    • Añadir setters y getters de propiedades que vamos a añadir en nuestra entidad.
    • Por defecto drupal console no deja ningún getter ni setter en esta interfaz.
  /**
   * Returns the color of the section.
   *
   * @return string
   *
   * Color in HEX format
   */
  public function getColor();

  /**
   * Sets the section Color.
   *
   * @param string $color
   *
   * Color in HEX format
   *
   * @return $this
   */
  public function setColor($color);

  • src/Entity/SectionEntity.php
    • Parte de Annotation:
      • Aquí vienen las clases y rutas relacionadas con la entidad creada.
    • Parte de la class:
      • Por defecto drupal console sólo nos deja preconfigurado las propiedades ID y Label.
      • También se añaden getters y setters necesarios.
      • En el mismo archivo añadimos sus propiedades y los métodos exigidos por la interfaz.
  1. Clases controladoras de la entidad
  • src/Form/SectionEntityForm.php
    • Añadir propiedades adicionales.
    • En nuestro caso añadimos el elemento color en el método form().
    • OJO: Las nombres de los elementos del formulario deben coincidr con el nombre de las propiedades.
    $form['color'] = [
      '#type' => 'color',
      '#title' => $this->t('Color'),
      '#default_value' => $mymodule_section->getColor(),
      '#description' => $this->t("Color for the Section."),
      '#required' => TRUE,
    ];
  • src/Form/SectionEntityDeleteForm.php
    • No hay nada que hacer en nuestro caso
  • src/SectionListBuilder.php
    • Hay que modificar los campos a ser mostrados en el Header y las filas
    //...
    $header['color'] = $this->t('Color');
    //...
    $row['color'] = $entity->getColor();
    //...
  1. Esquema de configuración
  • config/schema/mymodule_section.schema.yml
  • Añadimos las propiedades adicionales.
  • En nuestro caso:
    color:
      type: string
      label: 'Color'
  1. Definición de rutas y enlaces de menú
  • Enlaces:
    • mymodule.links.menu.yml
    • mymodule.links.action.yml
  • Menús:
    • Método 1 (rutas estáticas)
    • Método 2 (rutas dinámicas): Método usado por drupal console
      • src/SectionHtmlRouteProvider.php

Acceder a las entidades creadas

$query = \Drupal::entityQuery('mymodule_section');
$sections = $query->execute();

$section_storage = \Drupal::entityTypeManager()->getStorage('mymodule_section');
foreach($sections as $section_id) {
  $section = $section_storage->load($section_id);
};