Drupal 8: Entities

Working with entities in Drupal 8 modules
Drupal Meetup Stuttgart

06/11/2015

 

1. What are Entities?

loadable thingies, that can optionally be fieldable

https://www.drupal.org/node/460320

Entities are

  • Entity types - node, user, ...
    -> Base fields, like nid, title, author

     
  • Bundles - article, story, ...
    -> Bundle fields, like an image

All entities aren't equal, they may have different

Entities in Drupal 7 (Core)

  • Nodes
  • Users
  • Taxonomy vocabularies
  • Taxonomy terms
  • Files
  • Comments

Entities in Drupal 8

  • Entities in Drupal 8 are classes
  • Can be content entities or config entities
  • Extend corresponding base classes
class Contact extends ContentEntityBase implements ContactInterface {

    ...

}

Entity examples in Drupal 8 (Core)

  Content Entities

  Configuration entities

  • Aggregator feed / item

  • Block content

  • Comment

  • Message

  • File

  • Menu link

  • Content (aka node)

  • Shortcut

  • Taxonomy term

  • User

  • Action

  • Block

  • Breakpoint

  • Comment type

  • Content type

  • Date format

  • Field

  • Image Style

  • Language

  • Menu

  • Role

  • View

  • ...

2. Working with entities: CRUD

CRUD =

  • Create
  • Read
  • Update
  • Delete

entities, implemented by something called Entity API

The problem with D7:

  • Entity API is incomplete, only the R exists (entity_load)
  • Most missing parts implemented by contrib (entity module)
  • But many developers keep using proprietary D6 functions,
    still not removed from core:
    - node_load(), node_save()
    - user_load(), user_save()
    - taxonomy_get_term_by_name()

    - taxonomy_vocabulary_delete()
    - ...

Drupal 8: Entity API in core!

  • Streamlines the way of working with entities
  • Easy extendable / testable (OOP)
  • No need for proprietary stuff
     

3. Read entities (CRUD)

Drupal 7: proprietary functions

// Load a single node
$customer = node_load(526);

// Load multiple users
$users = user_load_multiple(array(77, 83, 121));

// Load a single term
$category = taxonomy_term_load(19);

Drupal 8: entity manager

// Load a single node
$storage = \Drupal::entityManager()->getStorage('node');
$customer = $storage->load(526);

// Load multiple users
$storage = \Drupal::entityManager()->getStorage('user');
$users = $storage->loadMultiple(array(77, 83, 121));

// Load a single term
$storage = \Drupal::entityManager()->getStorage('taxonomy_term');
$category = $storage->load(19);

Better: use Dependency Injection, not static calls!

Drupal 8: static calls

// Load a single node
$customer = Node::load(526);

// Load multiple users
$users = User::loadMultiple(array(77, 83, 121));

// Load a single term
$category = Term::load(19);

Drupal 8: procedural wrappers

// Load a single node
$customer = entity_load('node', 526);

// Load multiple users
$users = entity_load_multiple('user', array(77, 83, 121));

// Load a single term
$category = entity_load('taxonomy_term', 19);

4. Create entities (CRUD)

Drupal 7: generic classes

$node = new stdClass();
$node->type = 'article';
node_object_prepare($node);
$node->title = 'Breaking News';
node_save($node);
$storage = \Drupal::entityManager()->getStorage('node');
$node = $storage->create(array('type' => 'article', 'title' => 'Breaking News'));
$node->save();

Drupal 8: entity manager

$node = Node::create(array('type' => 'article', 'title' => 'Breaking News'));
$node->save();

Drupal 8: static call

5. Update entities (CRUD)

Drupal 7: proprietary functions

$node = node_load(331);
$node->title = 'Changed title';
node_save($node);

Drupal 8: entity manager

$storage = \Drupal::entityManager()->getStorage('node');
$node = $storage->load(526);
$node->setTitle('Changed title');
$node->save();

Drupal 8: procedural wrapper

$node = entity_load('node', 526);
$node->setTitle('Changed title');
$node->save();

6. Delete entities (CRUD)

Drupal 7: proprietary functions

node_delete(529);
node_delete_multiple(array(22,56,77));

Drupal 8: procedural wrapper

entity_delete_multiple('node', array(529));
entity_delete_multiple('node', array(22,56,77));
$storage = \Drupal::entityManager()->getStorage('node');
$node = $storage->loadMultiple(array(529));
$storage->delete($node);

$storage = \Drupal::entityManager()->getStorage('node');
$nodes = $storage->loadMultiple(array(22,56,77));
$storage->delete($nodes);

Drupal 8: entity manager

7. Accessing entities

Accessing entities in D7

$car = node_load(23);

$title = $car->title;
$color = $car->field_color['und'][0]['value']
$manufacturer = $car->field_manufacturer['und'][0]['target_id']

...

Or, thanks to Entity Metadata Wrapper (contrib):

$car = entity_metadata_wrapper('node', 23);

$title = $car->title;
$color = $car->field_color->value();
$manufacturer = $car->field_manufacturer->raw();

...

No getter / setter methods, but some lovely arrays:

Accessing entities in D8

$nid = $car->id();
$nid = $car->get('nid')->value;
$nid = $car->nid->value;

$title = $car->label();
$title = $car->getTitle();
$title = $car->get('title')->value;
$title = $car->title->value;

$created = $car->getCreatedTime();
$created = $car->get('created')->value;
$created = $car->created->value;

$color = $car->field_color->value;
$color = $car->get('field_color')->value;

$uid = $car->getOwnerId();
$uid = $car->get('uid')->target_id;
$uid = $car->uid->value;

$user = $car->getOwner();
$user = $car->get('uid')->entity;

Getter / setter methods in core, but ambivalent:

Reasonable, or just bad DX ?

Drupal\node\Entity\Node Object(
  [values:protected] => Array(
    [vid] => Array([x-default] => 1)
    [langcode] => Array ([x-default] => en)
    [revision_timestamp] => Array([x-default] => 1433958690)
    [revision_uid] => Array([x-default] => 1)
    [revision_log] => Array([x-default] =>  )
    [nid] => Array([x-default] => 1)
    [type] => Array([x-default] => test)
    [uuid] => Array([x-default] => 46b4af73-616a-494a-8a16-22be8dfe592e)
    [isDefaultRevision] => Array([x-default] => 1)
    [title] => Array([x-default] => Breaking News)
    [uid] => Array([x-default] => 1)
    [status] => Array([x-default] => 1)
    [created] => Array([x-default] => 1433958679)
    [changed] => Array([x-default] => 1433958679)
    [promote] => Array([x-default] => 1)
    [sticky] => Array([x-default] => 0)
    [default_langcode] => Array([x-default] => 1)
  )
  [fields:protected] => Array()
  [fieldDefinitions:protected] => 
  [languages:protected] => 
  [langcodeKey:protected] => langcode
  [defaultLangcodeKey:protected] => default_langcode
  [activeLangcode:protected] => x-default
  [defaultLangcode:protected] => en
  [translations:protected] => Array(
    [x-default] => Array([status] => 1)
  )
  [translationInitialize:protected] => 
  [newRevision:protected] => 
  [isDefaultRevision:protected] => 1
  [entityKeys:protected] => Array(
    [bundle] => test
    [id] => 1
    [revision] => 1
    [label] => Breaking News
    [langcode] => en
    [uuid] => 46b4af73-616a-494a-8a16-22be8dfe592e
    [default_langcode] => 1
  )
  [entityTypeId:protected] => node
  [enforceIsNew:protected] => 
  [typedData:protected] => 
  [_serviceIds:protected] => Array()
)

By the way...

$node->values['title']['x-default'] ?
$node->entityKeys['label'] ?

Don't even think of it!

8. Entity Queries

Drupal 7: Entity Field Query

$query = new EntityFieldQuery();

$query
  ->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', array('product', 'movies'))
  ->propertyCondition('status', 1)
  ->fieldCondition('body', 'value', 'discount', 'CONTAINS')
  ->propertyOrderBy('created', 'DESC');

$result = $query->execute();

if (!empty($result['node'])) {
  $nodes = node_load_multiple(array_keys($result['node']))
}

Useful, but

  • why is this called Entity Field Query?
  • why are there three condition types?
  • what's the result structure?

Drupal 8: Entity Query

$storage = \Drupal::entityManager()->getStorage('node');

$query = $storage->getQuery();

$query
  ->Condition('type', array('product', 'movies'))
  ->Condition('status', 1)
  ->Condition('body', 'value', 'discount', 'CONTAINS')
  ->OrderBy('created', 'DESC');

$result = $query->execute();

$nodes = $storage->loadMultiple($result);

9. There's even more...

Create your own custom

  • Entity types
  • Bundles
  • Entity forms
  • Access handlers
  • Storage controllers
  • ...

Thank You!

 

http://slides.com/drubb

http://slideshare.net/drubb

Drupal 8: Entities

By Boris Böhne

Drupal 8: Entities

Working with entities in Drupal 8 modules, a presentation at Drupal Meetup Stuttgart, 06/11/2015

  • 1,481