Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough
Feb 01 2018
Feb 01

Paragraphs is a powerful Drupal module that makes gives editors more flexibility in how they design and layout the content of their pages. However, they are special in that they make no sense without a host entity. If we talk about Paragraphs, it goes without saying that they are to be attached to other entities.
In Drupal 8, individual migrations are built around an entity type. That means we implement a single migration for each entity type. Sometimes we draw relationships between the element being imported and an already imported one of a different type, but we never handle the migration of both simultaneously.
Migrating Paragraphs needs to be done in at least two steps: 1) migrating entities of type Paragraph, and 2) migrating entities referencing imported Paragraph entities.

Migration of Paragraph entities

You can migrate Paragraph entities in a way very similar to the way of migrating every other entity type into Drupal 8. However, a very important caveat is making sure to use the right destination plugin, provided by the Entity Reference Revisions module:

destination: plugin: ‘entity_reference_revisions:paragraph’ default_bundle: paragraph_type destination:plugin:entity_reference_revisions:paragraphdefault_bundle:paragraph_type

This is critical because you can be tempted to use something more common like entity:paragraph which would make sense given that Paragraphs are entities. However, you didn’t configure your Paragraph reference field as a conventional Entity Reference one, but as an Entity reference revisions field, so you need to use an appropriate plugin.

An example of the core of a migration of Paragraph entities:

source: plugin: url data_fetcher_plugin: http data_parser_plugin: json urls: 'feed.url/endpoint' ids: id: type: integer item_selector: '/elements' fields: - name: id label: Id selector: /element_id - name: content label: Content selector: /element_content process: field_paragraph_type_content/value: content destination: plugin: 'entity_reference_revisions:paragraph' default_bundle: paragraph_type migration_dependencies: { } plugin:urldata_fetcher_plugin:httpdata_parser_plugin:jsonurls:'feed.url/endpoint'    type:integeritem_selector:'/elements'    name:id    label:Id    selector:/element_id    name:content    label:Content    selector:/element_contentfield_paragraph_type_content/value:contentdestination:plugin:'entity_reference_revisions:paragraph'default_bundle:paragraph_typemigration_dependencies:{  }

To give some context, this assumes the feed being consumed has a root level with an elements array filled with content arrays with properties like element_id and element_content, and we want to convert those content arrays into Paragraphs of type paragraph_type in Drupal, with the field_paragraph_type_content field storing the text that came from the element_content property.

Migration of the host entity type

Having imported the Paragraph entities already, we then need to import the host entities, attaching the appropriate Paragraphs to each one’s field_paragraph_type_content field. Typically this is accomplished by using the migration_lookup process plugin (formerly migration).

Every time an entity is imported, a row is created in the mapping table for that migration, with both the ID the entity has in the external source and the internal one it got after being imported. This way the migration keeps a correlation between both states of the data, for updating and other purposes.

The migration_lookup plugin takes an ID from an external source and tries to find an internal entity whose ID is linked to the external one in the mapping table, returning its ID in that case. After that, the entity reference field will be populated with that ID, effectively establishing a link between the entities in the Drupal side.

In the example below, the migration_lookup returns entity IDs and creates references to other Drupal entities through the field_event_schools field:

field_event_schools: plugin: iterator source: event_school process: target_id: plugin: migration_lookup migration: schools source: school_id field_event_schools:  plugin:iterator  source:event_school  process:    target_id:      plugin:migration_lookup      migration:schools      source:school_id

However, while references to nodes or terms basically consist of the ID of the referenced entity, when using the entity_reference_revisions destination plugin (as we did to import the Paragraph entities), two IDs are stored per entity. One is the entity ID and the other is the entity revision ID. That means the return of the migration_lookup processor is not an integer, but an array of them.

process: field_paragraph_type_content: plugin: iterator source: elements process: temporary_ids: plugin: migration_lookup migration: paragraphs_migration source: element_id target_id: plugin: extract source: '@temporary_ids' index: - 0 target_revision_id: plugin: extract source: '@temporary_ids' index: - 1 field_paragraph_type_content:  plugin:iterator  source:elements  process:    temporary_ids:      plugin:migration_lookup      migration:paragraphs_migration      source:element_id    target_id:      plugin:extract      source:'@temporary_ids'      index:        -0    target_revision_id:      plugin:extract      source:'@temporary_ids'      index:        -1

What we do then is, instead of just returning an array (it wouldn’t work obviously), use the extract process plugin with it to get the integer IDs needed to create an effective reference.

Summary

In summary, it’s important to remember that migrating Paragraphs is a two-step process at minimum. First, you must migrate entities of type Paragraph. Then you must migrate entities referencing those imported Paragraph entities.

More on Drupal 8

Top 5 Reasons to Migrate Your Site to Drupal 8

Creating your Emulsify 2.0 Starter Kit with Drush

Jun 20 2016
Jun 20

Preface

Wow. Entities. What a mess. I really struggled with this. There's an example of a database-based module not using them and one that does use them. I think it boiled down to me that what I was representing were reports, which seemed very similar to nodes (in hindsight, perhaps this should have been a content type all along), so I should use entities.

Entities

As I look through examples, trying to figure out how to get my menu routing to work with my database entries, it appears that I need to set them up as entities. I say that, looking at the xmlsitemap and dbtng_example and content_entity_example from the examples module. So, let me back up and learn about D8 Entities. It looks like entities were introduced in Drupal 7 and there is a guide for that, but it's based on D7, so the concepts stuff is ok, but the implementation guidance is outdated. There's a link at the top to take you to a D8-specific guide. The guide says it's just a holder, but I'm going to give it a go. If nothing else, perhaps this post will help others.


First, entity types. Either you're setting up a configuration entity or a content entity. I think content entity fits for me. Next, looking at requirements section of the content type doc, I need to setup src/Entity/GatedContentEntity.php file with docblock stuff that will give the loader the information it needs. Hey, checkout this helpful hint about double quotes in the annotations doc (post #1 reference)! That annotations doc doesn't provide what all you need, but I'll take those 3 lines to start off with. I think this doc may list all of the properties you can use with ContentEntityType, but not sure which ones I really need and how to use them. This is when the examples/content_entity_example/src/Entity/Contact.php file helped. I first just used the core form & access handlers for now.

Random Aside: Sublime Text 3

I use Sublime Text 3 as my IDE and there is a PHPDoc plugin that makes life editing these annotations easier. Package Manager makes it easy to install plugins: just follow the installation instructions (and restart ST), then follow the usage instructions to pull up the Install Package option and then type phpdoc and select it to install. Then restart ST again and you'll be much happier. I think the same applies for Sublime Text 2, too. This Drupal doc has some other helpful Sublime Text tips.

Back to it...

So I found this great doc on how to create your own content entity. And whoa ... this comment pointed me to the Drupal Console project, which can jumpstart this a LOT. So I tucked my handcrafted code away and ran this command:

drupal --target="fnmd8.local" gect --module="gated_content" --entity-class="GatedContent" --entity-name="gated_content" --label="Gated Content"

The end result is about 10 files with lots of boilerplate fields that don't match up with what I'm using. Maybe I'm going about this all wrong. Maybe I don't need Entities? Time to take a break...

After the weekend

So I went back and added the preface above and I feel I need to stick the course with Entities. Perhaps this post will be totally rewritten after I totally understand them and and write a better guide that flows better. I need to just release this post because I'm about to flip back to some D7 work and will be taking another break. I'll pick this post thread back up again shortly.

Apr 17 2013
joe
Apr 17

This week we are kicking off a brand new series, Working with Entities in Drupal 7. Entities were introduced in Drupal 7, and are an extremely useful tool, though they have been somewhat confusing for people to work with. In this series we will start out by explaining what entities are, in addition to things like bundles, fields, and entity types. We then spend time understanding how you can use the Entity API to work with existing Drupal entities in you own custom module work. With that foundation in place, we will create a new custom entity and talk about when and why you may, or may not, want to do that.

To get things started off we will cover some terminology and history, with a free video, and then begin working with entity_load() and the EntityFieldQuery class to work with existing Drupal entities on your system.

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 should brush up by watching our Module Development for Drupal 7 first.

Feb 07 2013
Feb 07

Episode Number: 

104

The Drupal 7 Conditional Fields module makes it easy to build dynamic and complex forms with Drupal 7 Fields. Any Drupal entity that has fields can pretty much be built into a dynamic and conditional form. The Conditional Fields module essentially lets you set conditions for how specific fields act based on another dependent field on the form. The simplest example is that this module can hide or show a field based on the value of another field. If you are still confused at what this module can do, watch the video to find out more!

In this episode you will learn:

  • The basic Drupal conditional fields terminology
  • How to hide and show Drupal fields based on the values of other form fields
  • How to get the module to work with nested field conditions

Thanks to Drupalize.me for sponsoring this episode!

DDoD Video: 

Oct 09 2012
Oct 09

With Drupal's custom content types, custom fields, and the addition of the popular Entity Reference module, site builders can whip up complex content models without a line of code. Editing those complex inter-related content types isn't always easy for content creators, though. The "Create a node, save it, then create its parent, then link the two" workflow is frustrating and error-prone. Fortunately, the Inline Entity Form module can help.

Screenshot of administration screen

Like many of the nifty Drupal tricks these days, Inline Entity Form is a custom field editing widget. On any content type with an Entity Reference field, choose it as the field's editing widget, and the rest is magic. When you create a new piece of content, you'll get the form to create the referenced entity on the same form. It works smoothly with multi-value fields, and can use a simple autocomplete picker to link existing entities if they already exist.

Screenshot of resulting change to site

The challenge of creating and populating complex nested content relationships has always been a tricky one in Drupal. Inline Entity Form was created by the Drupal Commerce team to simplify the management of complex product collections, and it solves the problem quite nicely.

*/
Jun 25 2012
Jun 25

Posted Jun 25, 2012 // 0 comments

Apache Solr is one of the great solutions for providing search functionality to one's site and there are many modules for Drupal that provide the functionality. The Search API and ApacheSolr modules are two great examples of such. I became a huge fan of the options that Search API provided until I ran into one major roadblock... the site(s) I was implementing search for, was hosted on Acquia and using Acquia's Solr service, which only supports the ApacheSolr module.

So, what's the drawback? Well, out of the box ApacheSolr only supports nodes for indexing. Taxonomy and entities are ignored, which for many of the requirements for my sites in progress was necessary. Was it the end of the world? Not at all. After a little research I found that taxonomy and other entities could be added for indexing by the simple implementation of hook_apachesolr_entity_info_alter.

Though I'm not directly demonstrating it, taxonomy can be included as well as Drupal (for the most part.) The taxonomy is treated like an entity.

Here's an example of using the hook to add some custom photo and text entities for indexing:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
 * Implements hook_apachesolr_entity_info_alter().
 *
 * Adds Text and Photo items to the search index.
 */
function tr_search_apachesolr_entity_info_alter(&$entity_info) {
  $entity_info['text_item']['indexable'] = TRUE;
  $entity_info['text_item']['status callback'] = 'tr_search_status_callback';
  $entity_info['text_item']['document callback'][] = 'tr_search_solr_document';
  $entity_info['text_item']['reindex callback'] = 'tr_search_solr_reindex_text_item';
  $entity_info['text_item']['index_table'] = 'apachesolr_index_entities_text_item';
  
  $entity_info['photo_item']['indexable'] = TRUE;
  $entity_info['photo_item']['status callback'] = 'tr_search_status_callback';
  $entity_info['photo_item']['document callback'][] = 'tr_search_solr_document';
  $entity_info['photo_item']['reindex callback'] = 'tr_search_solr_reindex_photo_item';
  $entity_info['photo_item']['index_table'] = 'apachesolr_index_entities_photo_item';  
}

Within that hook we are saying that we wish the two new entities to be included for indexing.

The structure of the $entity_info array is a series of sub-arrays keyed by the entity bundle name followed by a series values for the appropriate callbacks for each of the new entities.

For those elements, let's step through what each means with an example of a callback function.

  • "Indexable" - indicates to ApacheSolr that the entity can be indexed and exposes the entity within the ApacheSolr configuration pages in Drupal's admin.
  • "status callback" - indicates that the entity is enabled and available in the system
    Example:
    1
    2
    3
    4
    5
    6
    
    /**
     * Callback for the search status. Since all text and photo items are 'published', this is always true.
     */
    function tr_search_status_callback($term, $type) {
      return TRUE;
    }

    In this case, we are just returning TRUE, but more advanced logic could be implemented to indicate the status pending advanced needs.
  • "document callback" - callback to provide the content/values that will be sent to Solr server for indexing.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    
    /**
     * Builds the information for a Solr document.
     *
     * @param ApacheSolrDocument $document
     *   The Solr document we are building up.
     * @param stdClass $entity
     *   The entity we are indexing.
     * @param string $entity_type
     *   The type of entity we're dealing with.
     */
    function tr_search_solr_document(ApacheSolrDocument $document, $entity, $entity_type) {
      // Headline
      $document->label = apachesolr_clean_text((!empty($entity->field_tr_headline[LANGUAGE_NONE][0])) ? $entity->field_tr_headline[LANGUAGE_NONE][0]['value'] : '');
     
      // Credit
      $document->ss_credit = (!empty($entity->field_tr_credit[LANGUAGE_NONE][0])) ? $entity->field_tr_credit[LANGUAGE_NONE][0]['value'] : '';
     
      // Slug
      $document->ss_slug = (!empty($entity->field_tr_slug[LANGUAGE_NONE][0])) ? $entity->field_tr_slug[LANGUAGE_NONE][0]['value'] : '';
      $document->tus_slug = (!empty($entity->field_tr_slug[LANGUAGE_NONE][0])) ? $entity->field_tr_slug[LANGUAGE_NONE][0]['value'] : '';
     
      // Content
      if ($entity_type == 'photo_item') {
        $document->content = apachesolr_clean_text((!empty($entity->field_tr_caption[LANGUAGE_NONE][0])) ? $entity->field_tr_caption[LANGUAGE_NONE][0]['value'] : '');
      }
      else {
        $document->content = apachesolr_clean_text((!empty($entity->field_tr_text_body[LANGUAGE_NONE][0])) ? $entity->field_tr_text_body[LANGUAGE_NONE][0]['value'] : '');
      }
     
      $documents = array();
      $documents[] = $document;
      return $documents;
    }

    Pretty much checking the entity fields that we want to send we capture their values as properties of the solr document object and return
  • "reindex callback" - callback to provide instructions for when the content is being re-indexed in the system
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    
    /**
     * Reindexing callback for ApacheSolr, for text items
     */
    function tr_search_solr_reindex_text_item() {
      $indexer_table = apachesolr_get_indexer_table('text_item');
      $transaction = db_transaction();
      $env_id = apachesolr_default_environment();
      try {
        db_delete($indexer_table)
          ->condition('entity_type', 'text_item')
          ->execute();
          
        $select = db_select('text_item', 't');
        $select->addField('t', 'eid', 'entity_id');     
        $select->addExpression(REQUEST_TIME, 'changed');
     
        $insert = db_insert($indexer_table)
          ->fields(array('entity_id', 'changed'))
          ->from($select)
          ->execute();
      }
      catch (Exception $e) {
        $transaction->rollback();
        watchdog_exception('Apache Solr', $e);
        return FALSE;
      }
     
      return TRUE;
    }
  • "index_table" - the name of the database table that ApacheSolr will locally store references for.
    This table is one that you define in a *.install file using drupal's schema api. The table structure should mimic the same structure that ApacheSolr already defines for nodes.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    
    /**
     * Implements hook_schema().
     */
    function tr_search_schema() {
      $types = array(
          'text_item' => 'apachesolr_index_entities_text_item',
          'photo_item' => 'apachesolr_index_entities_photo_item',
      );
      foreach ($types as $key => $type) {
        $schema[$type] = array(
          'description' => t('Stores a record of when an entity changed to determine if it needs indexing by Solr.'),
          'fields' => array(
            'entity_type' => array(
              'description' => t('The type of entity.'),
              'type' => 'varchar',
              'length' => 128,
              'not null' => TRUE,
              'default' => $key,          
            ),
            'entity_id' => array(
              'description' => t('The primary identifier for an entity.'),
              'type' => 'int',
              'unsigned' => TRUE,
              'not null' => TRUE,
            ),
            'bundle' => array(
              'description' => t('The bundle to which this entity belongs.'),
              'type' => 'varchar',
              'length' => 128,
              'not null' => TRUE,
              'default' => $key,
            ),
            'status' => array(
              'description' => t('Boolean indicating whether the entity is visible to non-administrators (eg, published for nodes).'),
              'type' => 'int',
              'not null' => TRUE,
              'default' => 1,
            ),
            'changed' => array(
              'description' => t('The Unix timestamp when an entity was changed.'),
              'type' => 'int',
              'not null' => TRUE,
              'default' => 0,
            ),
          ),
          'indexes' => array(
            'changed' => array('changed', 'status'),
          ),
          'primary key' => array('entity_id'),
        );
      }
      return $schema;
    }

Using this base set of code you can be able to add any drupal entity to ApacheSolr for indexing. Not everything demonstrated may conform to ones exact needs but, the premise remains the same in allowing entities not supported out of the box to be added to search indexes.

(A hand to Brad Blake for contribution in the code as well)

Geoff is a developer at Phase2 who originally studied computer science in college before switching to culinary arts. Thus began a career that led Geoff to become an executive chef for different restaurants in Columbia, SC.

After close ...

Feb 21 2012
Feb 21

Entities in Drupal 7 simplify and centralize common logic that, in earlier versions of Drupal, was duplicated in several places, or only usable in specific modules. There are, however, many features (such as saving entities!) that did not make it into Drupal 7. The Entity API module fills in these missing gaps in the core and goes a step farther by simplifying definition of new entity types, and integration with contrib modules such as Views, Rules, and Features.

Generalized API

Core provides standardized entity loading using entity_load. There are however no functions to save, view, or delete entities! The Entity module defines entity_save, entity_view, and entity_delete functions. These new functions provide the other operations that are critical when code needs to work generally for multiple entity types. Normally you have to implement your own logic for saving an entity, and hope that you are properly invoking all the right hooks, but now you don’t have to worry about writing that yourself.

Clean Object-Oriented Design

All Drupal core entities are stdClass objects. The Entity API defines an Entity class which encapsulates the entity's properties (such as its type) into one object, and wraps many of the entity operation functions such as entity_save(), entity_label(), entity_uri(), entity_i18n_string(), etc. into methods. For example, instead of writing entity_save($entity_type, $obj), you can just write $obj->save(). You can of course extend this class when defining your own entities, which is what we’ve often chosen to do.

Another general upside to using classes in Drupal 7 is that files containing classes can be automatically loaded when they are needed, so any complex logic that you might need for your class will only need to be loaded on pages where the entity is actually used. This can be a plus for performance since it decreases the amount of code loaded on each page.

Automatic CRUD UI

No one likes building complex menu structures. Thankfully, the Entity module simplifies creation of standard UIs for managing entities. All you have to do is give it a base path for the interface and define the edit form, and from there the module can create add, edit and listing pages automatically, so you don’t have to.

Views and Rules integration

Integrating with other modules can be complicated, so the Entity module includes automatic integration with several modules, including Views and Rules. It will automatically give Views data about the structure of your entity by using the database schema or the entity properties. Similarly, because the loading and saving is done via the Entity module, it can automatically trigger events in the Rules module.

Exporting and Features integration

Exporting objects and configuration into code is a huge plus for both site deployment, and change tracking. The Entity module provides functions to export entities to JSON, and cleanly integrates with Features. To export a custom entity type, all that you need to do is use a specific entity controller, and define required exportable fields such as 'machine name' and ‘status’.

Standardized definition of properties

The same data that is used to provide integration with Views is available for any module to use. The Entity module provides the hooks hook_entity_property_info(_alter) ( see also ) for defining information about an entity type's properties. This property information includes the name along with metadata like data type, label and description, and if the value is required or needs to be sanitized.

This property data can be automatically generated by inspecting the entity's database table, or you can manually specify properties using hook_entity_property_info for more advanced behavior. Along with integration with Views, this data can then be used to automatically sanitize string data, or format numbers, or reference other tables.

Validation

Building on the Entity module's property definitions, you can specify validation callback functions to validate data for properties. Heavy reliance on the Form API validation in core and contrib means that it is often very hard to validate an entity programmatically and the only real option is to re-execute the form behind the scenes. By having metadata about properties easily available, the values can be validated properly without having to work through the Form API at all.

Conclusion

I hope this has motivated you a bit to take a look at the Entity module. Usage of the module is growing daily and you may already have it installed as a dependency for a contrib module. Several high-profile contrib modules, such as Organic Groups, Commerce, Rules, Search API and Field Collection, have the Entity module as a dependency and there are more all the time.

Sep 27 2011
Sep 27

In Drupal 6, module developers often use Nodes as an all-purpose method for having objects that can be saved into the database. This hack avoids having to write a lot of boilerplate CRUD for all custom data used in your modules. Nodes in D6 are a powerful tool for this use case when combined with the flexibility of CCK's custom fields, and the simplified integration with contrib modules. However, using Nodes for every piece of specialized content means a lot of overhead; contributed modules often modify Nodes and added hooks that operated on them. This is a major performance concern, not to mention a bad architecture for unrelated data.

In Drupal 7, we have entities. Entities not only provide all functionality available with Nodes in D6, but they offer much more. Many modules in core are now using Entities for their database records, including node.module and user.module. In this post, we'll discuss what Entities are, some poignant examples of Entities, and why you would want to use them.

What is an Entity?

Entities can be thought of as the parent class of nodes. They are the abstraction of functionality common between Nodes, Taxonomy Terms, and Users (among others). You can see this very clearly by looking at the Drupal 7 version of user_load_multiple() and node_load_multiple().

<?php
function user_load_multiple$uids = array(), 
                             
$conditions = array(),
                             
$reset FALSE) {
  return 
entity_load('user'$uids$conditions$reset);
}
function 
node_load_multiple$nids = array(),
                             
$conditions = array(),
                             
$reset FALSE) {
  return 
entity_load('node'$nids$conditions$reset);
}
?>

As you can see, the loading behaviour of nodes and users is almost identical. This makes a lot of code in Drupal 7 core more maintainable and much cleaner. Building on this, the API defines a consistent set of functions for getting information such as label and uri for an entity, which was often annoying extra work in D6. One of the biggest benefits, however, is that you can define your own custom entities, and they can also be fieldable. In short, you get all of the convenience of nodes without the overhead and unnecessary code.

Entities also have revision tracking support baked in, just like the the Node module. This lets you have multiple versions of the entity stored in the database, but without having to define the revision-loading logic yourself. For example, if you made a “Wiki page” entity, you could track changes to pages and, with some ingenuity, show a diff between two revisions. Setting up these tables and writing boilerplate SQL and loading code would be time consuming and error-prone, but with entities, you can get Drupal to d the hard work for you.

Examples of entities

Some notable Entity types are Nodes, Users, and Taxonomy Terms. However, many contributed modules have moved to Entities for this kind of functionality. Here are some notable modules that use Entities:

  • Wysiwyg: Uses entities for profiles.
  • Organic Groups: Uses entities for groups, membership types, and memberships.
  • Commerce: Uses entities for products, customers, payments, and line items.
  • Field Collection: Uses entities for “Field-collection items.” The Field collection module allows you to add fields to the “Field-collection items,” which then appear to be added to the entity that the field collection was originally attached to.
  • Relation: Uses entities for — you guessed it — relations. These entities link two other entities together. But, since relations are entities, the relationships themselves can have fields.

Benefits of Entities

Why are entities so cool? Here’s a short list:

Avoiding Boilerplate loading logic and SQL

Writing loading functions like node_load and boilerplate SQL is tedious and hard to maintain. With Entities, we can focus on the important functionality that is specific to our data type.

Consistent functionality between types

As I said before, entities have a standard interface. They have URIs, labels, and you can use a standard function to load them. This means more flexible, reliable code.

Not having to work with Nodes

Not having to work with Nodes for every main chunk of data makes your architecture better. Separating Node functionality from your own module’s functionality leads to more stable code. Even contributed modules that abuse nodes won’t get in your way. And the multitude of hooks running on Node operations can be trimmed down.

The contrib Entity API Module

The confusingly named contrib Entity API module provides even more functionality than Drupal core. In addition to all the benefits mentioned above, it provides saving, deleting, and updating entities, along with a ton of extra functionality. We’ll talk about this in the next part of this series.

Related Links

Want to learn more about Entities? Here are some links to get you started.

  • Ronald Ashri of Istos has an excellent three part series on building entities.

Slides and Video

At Drupalcamp Montreal, I gave a presentation of most of this. The slides are embedded and the video is available here: Videos

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web