Entity Api | Trabajando con entidades en Drupal 9
Al trabajar con entidades, en nuestros módulos personalizados, podremos realizar todo tipo de comprobaciones, para asegurarnos de obtener los cambios o respuestas que esperamos según su tipo o relación.
Si no ves el video, puedes refrescar el navegador, presionando (Ctrl+Shift+R | Ctrl+F5 o Shift+F5), o abrirlo directamente desde el Canal de Youtube... HAZ CLIC AQUI
Esta vez nos toca abordar el tema de Cómo trabajar con la API de entidades en Drupal 9 o (Entity API). Como mencionamos en el capítulo anterior sobre Tipos de entidad en Drupal 9, a partir de Drupal 8 se recomienda que escribamos funciones y métodos con interfaces en lugar de clases.
¿Que son las Interfaces?
Según la documentación oficial de PHP, en la programación orientada a objetos (OOP), las interfaces de objetos permiten crear código con el cual especificar qué métodos deben ser implementados por una clase, sin tener que definir cómo estos métodos son manipulados.
Las interfaces se definen de la misma manera que una clase, aunque reemplazando la palabra reservada class por la palabra reservada interface y sin que ninguno de sus métodos tenga su contenido definido.
Todos los métodos declarados en una interfaz deben ser públicos, ya que ésta es la naturaleza de una interfaz.
Para implementar una interfaz, se utiliza el operador implements. Todos los métodos en una interfaz deben ser implementados dentro de la clase; el no cumplir con esta regla resultará en un error fatal. Las clases pueden implementar más de una interfaz si se deseara, separándolas cada una por una coma.
En Drupal, para las entidades genéricas utilizaremos los métodos y propiedades de EntityInterface como en hook_entity_insert(EntityInterface $entity) y para trabajar con nodos específicos, utilizaremos los métodos y propiedades de NodeInterface como en hook_node_insert(NodeInterface $node).
Los métodos que cubren la mayoría de nuestras necesidades, cuando trabajamos con entidades genéricas son:
- Entity::create()
- Entity::load()
- Entity::save()
- Entity::id()
- Entity::bundle()
- Entity::isNew()
- Entity::label()
Comprobación de entidades (Check):
Al trabajar con entidades, en nuestros módulos personalizados, podremos realizar todo tipo de comprobaciones, para asegurarnos de obtener los cambios o respuestas que esperamos según su tipo o relación.
A continuación los ejemplos más frecuentes, en las operaciones de comprobación con entidades:
// Asegúrese de que un objeto sea una entidad. if ($entity instanceof \Drupal\Core\Entity\EntityInterface) { } // Asegúrate de que sea una entidad de contenido. if ($entity instanceof \Drupal\Core\Entity\ContentEntityInterface) { } // o también: if ($entity->getEntityType()->getGroup() == 'content') { } // Obtener el tipo de entidad o el ID del tipo de entidad. $entity->getEntityType(); $entity->getEntityTypeId(); // Asegúrate de que sea un nodo. if ($entity instanceof \Drupal\node\NodeInterface) { } // El uso de entityType () funciona mejor cuando el tipo de entidad necesario es dinámico. $needed_type = 'node'; if ($entity->getEntityTypeId() == $needed_type) { }
Obtener información de una entidad / métodos de entidad:
Existe varios métodos genéricos disponibles para obtener información de una entidad, como el ID, el paquete, el ID de revisión, etc. Consulte la documentación de EntityInterface para obtener más detalles.
// Obtiene el ID de la entidad. $entity->id(); // Obtiene el paquete. $entity->bundle(); // Comprueba si la entidad es nueva. $entity->isNew(); // Obtén la etiqueta de una entidad. Reemplazo de entity_label(). $entity->label(); // Obtener el objeto URL de una entidad. $entity->toUrl(); // Obtener ruta interna, alias de ruta si existe, para una entidad. $entity->toUrl()->toString(); // Cree un duplicado que se pueda guardar como una nueva entidad. $duplicate = $entity->createDuplicate();
Creación de entidades:
// Es recomendable que utilicemos el Entity Manager para crear entidades. $node = \Drupal::entityTypeManager()->getStorage('node')->create(['type' => 'article', 'title' => 'Another node']); // Podemos usar el método estático create () si conocemos la clase de entidad. $node = Node::create([ 'type' => 'article', 'title' => 'The node title', ]);
Los valores predeterminados de configuración de la anotación de tipo de campo solo se agregan para las claves de nivel superior que faltan; no se realiza una fusión profunda.
Evita usar el método estático Entity::create() en código orientado a objetos. En su lugar, use la inyección de dependencia para inyectar el administrador de tipos de entidad y crear la entidad con $this->entityTypeManager->getStorage($entity_type)->create(). Esto asegura que el código esté desacoplado correctamente y se pueda probar unitario.
Si quieres saber más sobre la Inyección de Dependencias, te lo cuento en este artículo: Cómo crear un servicio personalizado en Drupal 9
Para lograr la visibilidad dentro de un IDE, también puede asignar la interfaz de almacenamiento de la entidad a una propiedad. Por ejemplo, $this->nodeStorage = $this->entityTypeManager->getStorage('node'); Para crear una entidad, puede usar $this->nodeStorage->create().
Carga de entidades (Load):
// Usando el controlador de almacenamiento (recomendado). $entity = \Drupal::entityTypeManager()->getStorage($entity_type)->load(1); // Usa el método estático $node = Node::load(1); // Carga varias entidades, también existe como entity_load_multiple(). $entities = \Drupal::entityTypeManager()->getStorage($entity_type)->loadMultiple([1, 2, 3]); // Cargar entidades por sus valores de propiedad. $entities = \Drupal::entityTypeManager()->getStorage('node')->loadByProperties(['type' => 'article']);
Para actualizar una entidad, cárguela y luego guárdela con sus cambios.
Evite usar el método estático Entity::load() en código orientado a objetos. En su lugar, use la inyección de dependencia para inyectar el administrador de tipos de entidad y cargar la entidad con $this->entityTypeManager->getStorage($entity_type)->load($entity_id). Esto asegura que el código esté desacoplado correctamente y se pueda probar unitario.
Si quieres saber más sobre la Inyección de Dependencias, te lo cuento en este artículo: Cómo crear un servicio personalizado en Drupal 9
Guardar los cambios en la entidad (Save):
// Para guardar los cambios en una entidad. $entity->save();
Eso funciona tanto para entidades nuevas como existentes, la propia entidad realiza un seguimiento de si es nueva o no. De forma predeterminada, para las entidades de contenido, eso depende de si tiene un ID o no. Para guardar una entidad que tiene un ID como una entidad nueva (por ejemplo, al importar algo), se puede aplicar la marca isNew.
// Lo siguiente intentará insertar un nuevo nodo con el ID 5, esto fallará si ese nodo ya existe. $node->nid->value = 5; $node->enforceIsNew(TRUE); $node->save();
Eliminar entidades (Delete):
// Eliminar una sola entidad. $entity = \Drupal::entityTypeManager()->getStorage('node')->load(1); $entity->delete(); // Elimina varias entidades a la vez. \Drupal::entityTypeManager()->getStorage($entity_type)->delete([$id1 => $entity1, $id2 => $entity2]);
Consultando entidades (Query):
$entity = \Drupal::entityTypeManager()->getStorage('node'); $query = $entity->getQuery(); $ids = $query->condition('status', 1) ->condition('type', 'article')#type = ID de paquete (nombre de la máquina) #->sort('created', 'ASC') #ordenada #->pager(15) #límite de 15 artículos ->execute(); // Cargar carga de artículo único o múltiple($id) $articles = $entity->loadMultiple($ids);
Control de acceso a entidades (Access control):
El método access() se puede utilizar para comprobar quién puede hacer qué con una entidad. El método admite diferentes operaciones, las operaciones estándar son ver, actualizar, eliminar y crear, crear es algo especial, ver más abajo.
Las comprobaciones de acceso se envían al controlador de acceso.
// Verifique el acceso a la vista de una entidad. // De forma predeterminada, se verifica el acceso del usuario que ha iniciado sesión actualmente.. if ($entity->access('view')) { } // Compruebe si un usuario determinado puede eliminar una entidad. if ($entity->access('delete', $account)) { }
Al marcar el acceso de creación, generalmente no hay una entidad todavía. Crear uno solo para comprobar si alguien podría crearlo es una operación costosa. Por lo tanto, la creación de acceso para aquellos debe verificarse directamente en el controlador de acceso.
\Drupal::entityTypeManager()->getAccessControlHandler('node')->createAccess('article');
Si ya existe una entidad, $entity->access('create') también funciona, que solo reenvía al método createAccess(), de la misma manera que otras operaciones reenvían al método access () en el controlador de acceso.
NOTA: Algunas guías en línea usan \Drupal::entityManager(), pero está obsoleto en 8.x y se eliminará en 9.x. Entonces puede usar \Drupal::entityTypeManager() en lugar de \Drupal::entityManager().
Fuente: https://www.drupal.org/docs/drupal-apis/entity-api/working-with-the-entity-api#s-delete