Working with Entities in Drupal 7

This page is archived

We're keeping this page up as a courtesy to folks who may need to refer to old instructions. We don't plan to update this page.

Alternate resources

Entities were introduced in Drupal 7 as a way of taking the things that people loved about nodes + CCK in Drupal 6 and applying them to other types of data like users, comments, and taxonomy terms. The Entity API in Drupal 7 provides a set of common functions and classes to make it easier for developers to create their own custom entity types or to work with other already existing ones in a generic way. The API in Drupal core however is still missing some really useful tools and is supplemented by the Entity module in Drupal contrib which we'll make heavy use of throughout the series.

In this series we'll learn about the interplay between Entities, Entity Types, Bundles, and Fields and how to write custom code to deal with each of these things. The Entity API demo site files that we use in this series is all located in the Lullabot GitHub, as well as in zip files, which are attached to the respective video pages, under the Downloads tab.

This series covers:

  • What entities are and how they fit into the Drupal ecosphere
  • EntityFieldQuery
  • Entity classes, what they do and how to override them
  • Providing an admin UI for adding/editing and deleting entities from Drupal
  • Making entities fieldable
  • View modes
  • Creating custom UI's for dealing with entities
  • Describing entity properties to Drupal
  • Views integration for entities
  • Entity Metadata wrappers
  • Making entities revisionable

And much much more. This series assumes that you're already familiar with the basic tennents of writing modules for Drupal and makes use of things like hook_menu() without spending time explaining them. If you're not familiar with Drupal module development, you might want to brush up by watching our Module Development for Drupal 7 first.

Tutorials in this course
More information

Entities were introduced in Drupal 7 as a way of taking the things that people loved about nodes + CCK in Drupal 6 and applying them to other types of data like users, comments, and taxonomy terms. The Entity API in Drupal 7 provides a set of common functions and classes to make it easier for developers to create their own custom entity types or to work with existing ones in a generic way. The API in Drupal core however is still missing some really useful tools and is supplemented by the Entity module in Drupal contributed which we'll make heavy use of throughout the series.

In this series we'll learn about the interplay between Entities, Entity Types, Bundles, and Fields and how to write custom code to deal with each of these things. The Entity API demo site files that we use in this series are all located in the Lullabot GitHub, as well as in zip files attached to the respective video pages, under the Downloads tab.

This series covers:

  • What entities are and how they fit into the Drupal ecosphere
  • EntityFieldQuery
  • Entity classes, what they do and how to override them
  • Providing an admin UI for adding/editing and deleting entities from Drupal
  • Making entities fieldable
  • View modes
  • Creating custom UI's for dealing with entities
  • Describing entity properties to Drupal
  • Views integration for entities
  • Entity Metadata wrappers
  • Making entities revisionable

And much much more. This series assumes that you're already familiar with the basic tenets of writing modules for Drupal and makes use of things like hook_menu() without spending time explaining them. If you're not familiar with Drupal module development, you might want to brush up by watching our Module Development for Drupal 7 first.

Additional resources

Entity API Demo site files on GitHub
Entity module at Drupal.org

More information

In this lesson Joe will explain what an entity is and provide a little bit of history about how they came into being. We’ll also learn about some of the differences between custom entities and nodes (which happen to be a type of entity) and when, and why you might want to choose to write your own custom entities instead of using the node system or a more traditional datastore.

More information

This lesson takes a look at working with the already existing entities in Drupal such as users and nodes and demonstrates some best practices for working with them in your own custom module. We'll focus on writing code that will work with any entity type and isn't hard coded to work with just nodes or just entities.

Additional notes:
There is a typo in the video. Joe created the variable $types = 'comment'; in one spot and then used it as entity_load($type, ... which obviously wouldn't work because the later is missing an 's' on the end. The downloadable code for this video doesn't have the typo.

Additional resources

Entity API demos on GitHub

More information

This lesson will explore the use of EntityFieldQuery to retrieve lists of entities from Drupal without directly querying the database which can be problematic in a system where the underlying schema can change depending on configuration settings in the user interface. Again focusing on writing code that will work with any entity in Drupal and isn't hard coded to your particular setup.

Additional resources

EntityFieldQuery documentation

More information

In the next set of lessons we're going to be writing to the code to create our own custom entity type. The goal is to create a video entity that stores embed codes for YouTube videos and allows us to display the videos on our site. In this scenario we don't want all the overhead that comes with using the node system, like comments for example, so instead we're going to write our own custom entity for storing the data. We're going to take a look at the completed entity type that we're attempting to build and just walk through all the various components. We'll take a look at creating/updating, and deleting a video via the UI, and also the views integration and fieldability of our custom video entities.

More information

This lesson demonstrates the bare minimum needed to create a custom entity type and to load an Entity from the database. We’ll look at implementing a minimum viable hook_entity_info, talk about the relationship between the Entity API and the Schema API and use entity_load to retrieve a single entity record from the database.

Note, although it would be considered best practices to name the entity with the name of the module, e.g. videoentity_video, we did not include the module name prefix here because it is tedious to type it all out and to say "videoentity_video" without confusing people.

In the next lesson we'll cover the various entity classes and how they work. However, if you just want to get straight to using your entity and doing things like $entity = entity_load(); you'll need to declare a controller for your new entity type. Simply add this 'controller class' => 'EntityAPIController' in hook_entity_info(). That will get you started, and well talk about what exactly that line does in the next lesson.

Note: the video doesn't mention the 'primary key' element in the schema array (although it is in the code). This bit is necessary for the schema to install properly and work with the Entity API so if you're following a long make sure you add that part as well.

Additional resources

More information

This lesson introduces students to Entity classes and illustrates what each of the main Entity classes does, followed by a more in depth look at the CRUD operations provided by the base entity class, and finally demonstrates overriding the default Entity class with our own custom Entity object to define a defaultUrl() for our entities and a new implementation of hook_menu where we can view an entity.

Note: At the end of the this video code is added to hook_entity_info() that references a VideoEntityUIController class, however, the definition of that class is in our sample code, but was not shown being added here. And it is necessary to follow along with the videos. If you're following along you'll want to add the following code to the bottom of your videoasset.module file. If you're curious about what it does it's explained in the last part of this video.


/**
 * Our custom controller for the admin ui.
 */
class VideoEntityUIController extends EntityDefaultUIController {}

Additional resources

Entity API demos on GitHub

More information

Update your hook_entity_info implementation to take advantage of the Admin UI provided by the Entity API and quickly provide users of your site access to all the Entity CRUD operations via the UI. The API gives us a really good head start but we still need to write some code in order to provide a useable form for administrators. The API doesn’t make any assumptions about things like validating input so we also need to take care of that ourselves.

This video adds a new permission that allows privileged users administer our new videoasset entities. If you're following along as a user other than user 1 you'll need to make sure you give yourself the proper permissions. In the video, I'm logged in as the user with the ID of 1 so I'm just granted the permissions automatically.

Note: If you're following along with the videos in sequence there's an error that needs correcting. At the end of the previous video code was added to videoentity_entity_info() that references a VideoEntityUIController class, however, the definition of that class was not added. Which, will cause a PHP error because the class is missing.

In order to correct this error, you'll want to add the following code to the bottom of your videoentity.module file. This just ensures that the class is defined so that there are no errors. If you're curious about what it does it's explained in the last part of the previous video.


/**
 * Our custom controller for the admin ui.
 */
class VideoEntityUIController extends EntityDefaultUIController {}

In a later tutorial in this series, we'll customize the form for our video entity by adding more code to this class.

Note: At 14:10 on line 36 this line is added:

'#value' => isset($VideoAsset->id) ? t('Update video asset') : t('Save video 
asset'),

It should be:

'#value' => isset($video->id) ? t('Update video asset') : t('Save video 
asset'),
More information

So far we’ve seen that you can use entity_load and entity_view to display your entity. But what if you want more control over how your content gets rendered? In this lesson we’ll take a look at overriding the buildContent() method of our entity controller to spruce up the output a bit. We'll also overrid the save() method of the controller in order to populate the created_at and updated_at fields automatically when saving a video entity.

Note: In order to improve upon the security of the code in this lesson you'll want to make sure you're escaping all user input properly. The following code:


$build['embedcode'] = array(
      '#type' => 'markup',
      '#markup' => '<iframe width="560" height="315" src="http://www.youtube.com/embed/'. $entity->embedcode . '" frameborder="0" allowfullscreen></iframe>',
    );

Should be updated to use the check_url() function when outputting $entity->embedcode to ensure that user entered content is safe for use in the context of a URL.


$build['embedcode'] = array(
      '#type' => 'markup',
      '#markup' => '<iframe width="560" height="315" src="http://www.youtube.com/embed/'. check_url($entity->embedcode) . '" frameborder="0" allowfullscreen></iframe>',
    );
More information

Bundles are an implementation of an entity type to which fields can be attached. In this lesson we’ll take a look at configuring a single bundle type for our entities in order to allow us to make them fieldable by hardcoding the bundle information into hook_entity_info(). This is the most basic implementation of bundles. Then we’ll look at adding the ability to attach fields to our newly created bundle.

More information

Probably the most common use case for view modes is teaser nodes. Or, a node being rendered in the teaser view mode. View modes allow entities to be displayed different depending on context, and also allow other modules like Field API that participate in the entity rendering process to adjust their behavior depending on the requested view mode.

In this lesson we’re going to take a look at an ‘authenticated’ view mode that we can use to adjust the display for any authenticated users. Then we’ll update Entity Controller class and make use of this new view mode in our ::view() method.

NOTE: in the video Joe forgot to change the 'member' label to "Member" and then later in the video when we view it in the UI it is corrected. The sample code included with this video has the correct label.

More information

This lesson takes a look at exposing the data in our entities to views. Lucky for us the entity API handles a lot of this for us. We’ll take a look at what we get for free, using the EntityDefaultViewsController class provided by Entity API module. We'll also discuss ways that we can customize this controller, which we'll tackle in a later lesson.

More information

In this lesson we're going to take a more in-depth look at the UI controller we used earlier to create our administrative UI for the entity. We'll walk through how the controller adds menu paths and the like, without us needing to do any extra work, and then clean up our form-builder functions by overriding the UI controller's method, so that we can gain control of the name of the function that's called.

More information

In order to make the most of the entity APIs integration with other modules, such as Views, we need to describe the properties of our entity in more detail. The API can infer some information about a property based on our schema but we need to tell it that the integer stored in the updated_at column is actually a timestamp. We will do this by implementing hook_entity_property_info() and describing each of our entities properties. With these definitions in place you will be able to use the formatters in Views much like you would for individual fields on content types provided by core.

Note: Before you implement hook_entity_property_info() the API makes an educated guess about each property but once you've defined a single property, the API expects you to define all of the properties for your entity. Use the .install file in your module to get a complete list of the properties you need to define with hook_property_entity_info. You can also define additional properties that aren't mapped to fields in the database (these can be used for static properties).

Additional resources

Entity Property Information

More information

If you've done any module development, you're probably familiar with hook_node_view and Drupal's arrays of doom. In this lesson we'll show you how to get easier access to the same information using entity metadata wrappers. We will use the entity_metadata_wrapper function to retrieve a new EntityMetaDataWrapper object that provides an interface for easily accessing an entities property and field values. We'll use the getPropertyInfo method to expose information about individual properties, and the getIterator method to access fields that contain multiple values, such as tags. You'll see that by using meta data wrappers you can also access properties on referenced entities, such as the email address of the author of a node, without having to load that information independently.

Metadata wrappers also provide a consistent way to access properties common to all entities. For example, every entity in Drupal has a unique ID property or a human readable label, but these properties often have different names. User name vs. node title. Metadata wrappers allow you to access this information in a consistent way.

Additional resources

Entity metadata wrappers

More information

Revisions are an important concept in a content management system. Keeping track of all the edits that have been made to a particular entity over the course of its lifetime. A paper trail or sorts. This lesson takes a look at what is required in order to make our Entities support revisions.

If you've worked with Drupal's node system and enabled revisions then you've seen Drupal's basic revision handling in action. Every time you save a node, it creates a new version of that node. You can roll back to previous versions and keep track of how a piece of content has changed over time. Entity API also supports the concept of revisions and in this lesson we're going to take a look at adding revision support for our video entities.

In order to take advantage of this feature, we'll need to modify our database schema to accommodate storing multiple versions of the same entity. We'll move all fields that we want to make "revisionable" into a separate table and set up a new unique version ID field so that we can keep track of revisions.

Then we will update our hook_entity_info implementation to tell the API that we want to use the revision system and make some changes to the code in our VideoEntityController so that when an entity is updated we save a revision instead of overwriting the current data.

Finally we'll need to write a simple UI for viewing older versions of our video entity because the Entity API does not provide us with this code by default.

This course appears in the following guides:
Categories
Module Development, Backend and Infrastructure
Drupal 7, 8, 9, and 10