Drupal 8 Entities

Chad Peppers

Senior Drupal Developer & Architect

Littler Mendelson

http://www.drupal.org/u/chadmandoo

Following Along

http://slides.com/chadpeppers/deck-2

Overview

What are entities?

Working with the Entity CRUD.

Finding Entities with EntityQuery.

Entity hooks 

Drupal Learning Curve

Assumptions

  • You have installed Drupal before
  • You are familiar with Drupal Administration
  • Understand basic field system

What are entities?

  • Core Drupal Entities
  • Contrib module Entities
  • Custom Entities

Types of Entities

  • Configuration Entities
  • Content Entities

Entity Structure

// Add code here showing extending from the entity class, and then Nodes extending from the ContentEntity class

// Base Entity Class
abstract class Entity implements EntityInterface {
    // Code
}

// Content Entity
abstract class ContentEntityBase extends Entity implements \IteratorAggregate, ContentEntityInterface, TranslationStatusInterface {
    // Code
}

class Node extends ContentEntityBase implements NodeInterface {
    // Code 
}

// Configuration Entity
class Block extends ConfigEntityBase implements BlockInterface, EntityWithPluginCollectionInterface {
    // Code
}

abstract class ConfigEntityBase extends Entity implements ConfigEntityInterface {
    //
}

Terminology

  • Bundles
  • Fields

Drupal 7 vs Drupal 8

Drupal 7 Drupal 8
Extended entity functionality requires the Entity contrib module

Entities were generic stdClass objects.


 
Entity API built into core.


Entities are now specifically typed objects, with each entity type defining a class that will be used for instances of the given entity
 

Entity CRUD

CREATE

D8

<?php

// Procedural - There is no entity_save() anymore
$node = entity_create('node', array('title' => 'My Title', 'type' => 'page'));
$node->save();

// Static Call
$node = Node::create(['type' => 'page']);
$node->set('title', 'My Title');
$node->save();

// Entity Manager
$info = array('type' => 'page', 'title' => 'My Title');
$node = \Drupal::entityTypeManager()->getStorage('node')->create($info);
$node->save();

D7

<?php
// Using Drupal Core.
global $user;
$node = new stdClass();
$node->title = "My Title";
$node->type = "basic_page";
node_object_prepare($node);
$node->language = LANGUAGE_NONE; 
$node->uid = $user->uid; 
$node->status = 1; 
$node->promote = 0; 
$node = node_submit($node); 
node_save($node);

// Using Entity API
$node = entity_create('node', array('type' => 'basic_page'));
$entity = entity_metadata_wrapper('node',$node);
$entity->title->set("My Title");
$entity->save();

READ

D8

<?php
// Procedural Calls
$node = entity_load('node', 1);
$nodes = entity_load_multiple('node', array(1, 2, 3));

// Static Calls
$nid = 1;
$node = Node::load($nid);

$nids = array(1, 2, 3);
$nodes = Node::loadMultiple($nids);

// Using the Entity Manager
$storage = \Drupal::entityManager()->getStorage('node');
$node = $storage->load(1);
$nodes = $storage->loadMultiple(array(1, 2, 3));

D7

<?php

// Using Drupal Core Functions
$nid = 1;
$node = node_load($nid);

// Both code below does the same thing
$nids = array(1, 2, 3);
$nodes = node_load_multiple($nodes);
$node_entities = entity_load('node', $nids);

// Using the Entity API
$node_entity = entity_load_single('node', $nid);

// Loading taxonomy
$term = taxonomy_load_term(25);

// Loading a user
$user = user_load(1);

UPDATE

D8

<?php
// Procedural there is no entity_save
$node = entity_load_single('node', 1);
$node->save()

// Static calls
$nid = 1;
$node = Node::load($nid);
$node->set('title', 'My Awesome New Title');
$node->set('field_my_field', 'My New field');
$node->save();

// Storage Manager
$storage = \Drupal::entityManager()->getStorage('node');
$node = $storage->load(123);
$node->set('field_my_field', 'value');
$node->save();

D7

<?php
// Drupal core
$nid = 1;
$node = node_load($nid);
$node->title = "My New Title";
node_save($node);

// Entity API
$nid = 1;
$node_entity = entity_load_single('node', $nid);
$node_wrapper = entity_metadata_wrapper('node', $node_entity);
$node_wrapper->title->set('My Title');
$node_wrapper->save();

DELETE

D8

<?php
// Procedural - there is no entity_delete
entity_delete_multiple('node', array(1));

// Static call 
$nid = 1;
$node = Node::load($nid);
$node->delete();

// DELETE
$storage = \Drupal::entityManager()->getStorage('node');
$node = $storage->load(123);
$node->delete();

D7

<?php
$nid = 1;
node_delete($nid);

// Entity API
$nid = 1;
$node_entity = entity_load_single('node', $nid);
$node_wrapper = entity_metadata_wrapper('node', $node_entity);
$node_wrapper->delete();

Accessing Entity Values

// Drupal 7 Core
$node = node_load(1);
$title = $node->title;
$field = $node->field_my_field[LANGUAGE_NONE][0]['value'];

// Entity Metadata Wrapper
$node = node_load('node', $node);
$wrapper = entity_metadata_wrapper('node', $node);
$title = $wrapper->title->value();
$field = $wrapper->field_my_field->value();

// D8
$node = Node::load(1);
$node_array = $node->toArray();

// Various ways to get title
$title = $node->get('title')->value;
$title = $node->get('title')->getString();

// Referenced Entity
$node->get('field_my_reference')->referencedEntities();

// Chaining Methods
$node->get('field_my_reference')->referencedEntities()[0]->get('name')->getString()

EntityQuery

D8

<?php

$nids = \Drupal::entityQuery('node')
      ->condition('status', 1)
      ->condition('type', 'page')
      ->condition('field_my_field', 'My Value')
      ->execute();

if (!empty($nids)) {
    foreach ($nids as $nid) {
        $basic_page = Node::load($nid);

        // Do Sweet Stuff With Your Loaded Node.
    }
}

EntityFieldQuery

D7

<?php
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'article')
  ->propertyCondition('status', NODE_PUBLISHED)
  ->fieldCondition('field_news_types', 'value', 'spotlight', '=');

$result = $query->execute();

if (isset($result['node'])) {
  $news_items_nids = array_keys($result['node']);
  $news_items = entity_load('node', $news_items_nids);
} 

Entity Hooks

hook_entity_load
hook_ENTITY_TYPE_load
hook_entity_storage_load

Loading Hooks

Pre Render Hooks

hook_entity_prepare_view
hook_entity_view
hook_ENTITY_TYPE_view
hook_entity_view_alter

Entity Hooks

CRUD Hooks

hook_entity_create
hook_ENTITY_TYPE_create
hook_entity_insert
hook_ENTITY_TYPE_insert
hook_entity_update
hook_ENTITY_TYPE_update
hook_entity_presave
hook_ENTITY_TYPE_presave
hook_entity_predelete
hook_ENTITY_TYPE_predelete

hook_entity_delete
hook_ENTITY_TYPE_delete
hook_entity_revision_delete
hook_ENTITY_TYPE_revision_delete
hook_entity_prepare_form
hook_ENTITY_TYPE_prepare_form

Entity Hooks

Translation Hooks

hook_entity_translation_create
hook_ENTITY_TYPE_translation_create
hook_entity_translation_insert
hook_ENTITY_TYPE_translation_insert
hook_entity_translation_delete
hook_ENTITY_TYPE_translation_delete

Entity Hooks

Access Hooks

hook_entity_access
hook_ENTITY_TYPE_access
hook_entity_create_access
hook_ENTITY_TYPE_create_access

Live Examples

Common Questions

  • Why would I create my own Entity Type?
  • Why should I not use my own table for data?

 

Summary

  • Entities are integral part of Drupal
  • Entities has changed from D7 to D8
  • Drupal has a core Entity CRUD API
  • Find Entities safely using EntityQuery
  • Entity API has lots-o-hooks

References

https://www.drupal.org/docs/7/api/entity-api/an-introduction-to-entities

 

https://drupalize.me/tutorial/entity-api-overview?p=2792

 

https://docs.acquia.com/tutorials/fast-track-drupal-8-coding