Tweaking an EntityFieldQuery in Drupal

In Drupal 7/8 there are many ways to perform business logic, or retrieve data from an underlying storage system, such as the default Database. Drupal provides many Storage APIs to interact with storage mechanisms through a high level facade. For a given Entity for instance we could write queries to a database using the Database API, we could ask for a piece of field data directly from the Field API, or we could use EntityFieldQuery (EFQ) to query for a list of Entity IDs we want to examine further. This post will look at the last option, using EntityFieldQuery.

EntityFieldQuery was added to Drupal 7 as a class usable by developers. An EFQ can query all Entities based on Conditions. It has similar syntax to a database query written using say db_select(), but by the virtue of supplying an EFQ, your business logic (may) query any backend storage supported by Drupal. This adds a layer of portability above hardcoding database queries to retrieve your results. If your site infrastructure were to change to a storage engine such as MongoDB — your existing “find me all articles with condition X” would still work; and your site would benefit form a NoSQL backend vs. an SQL backend.

Using EntityFieldQuery

A simple EntityFieldQuery looks like this:

// build our query and execute it.
$bundle = 'course';
$efq = new EntityFieldQuery();
$efq->entityCondition('entity_type', 'node')
    ->entityCondition('bundle', $bundle)
    ->propertyOrderBy('nid', 'ASC')
    ->range(0,10000);
$result = $efq->execute();

// Do something with the results.
foreach (array_keys($result['node']) as $i => $nid) {
  $node = node_load($nid);
  $lang = $node->language;
  $node->field_coursedb_display_order[$lang] = array(0 => array('value' => $node->nid));
  node_save($node);
}

As you can see this has the concept of Conditions, Ordering, Ranges — just like an SQL query. In Drupal 7 a limit exists on EFQ that it cannot Join on related content (in this case Join is an SQL term reference). So in Drupal 7 you must make your selections from 1 piece of content … or is there another option.

note: To my knowledge Drupal 8 has solved this issue of not being able to query more complex relations using EFQ.

Modifying an EntityFieldQuery

EFQs are translated to the query language of the underlying storage mechanism. So if you’re using an SQL database for Drupal — ultimately your nifty EFQ will be changed into an SQL query. This sql query can be affected by Drupals hook_query_alter() function.  I’ve shown hook_query_alter() before in blog posts, but typically I show its usage directly on an SQL query, or a Views query — this is now an EFQ! Here is a brief example:

// Within some function of yours, you execute your query; giving it a Tag.
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'MYCONTENTTYPE')
  // Must call the method fieldCondition on field_A and field_B so
  // they get included in the SQL INNER JOIN statement.
  ->fieldCondition('field_A')
  ->fieldCondition('field_B')
  ->addTag('DoFunkyFieldLogic');
$query_result = $query->execute();
// ... make use of results

//
// ... elsewhere in your custom module ...
//

// Implements hook_query_TAG_alter
function mymodule_query_DoFunkyFieldLogic_alter(QueryAlterableInterface $query) {
  if ($query->hasTag('DoFunkyFieldLogic')) {
    // You will likely need to install Devel and call dpm($query) here.
    // Or else you wont know what the field names are in the raw SQL ...
    // you might be able to cheat and use full database table names and
    // column names, eg:
    //dpm($query);
    $query->where("field_data_field_A1.field_A_value + field_data_field_B2.field_B_value <= :my_quantity", array(':my_quantity' => variable_get('my_quantity', 5));
  }
}

Also, since EntityFieldQuery is a PHP class — you can create your own EFQ classes and add Tags for query altering, default conditions for EFQ and other nifty tweaks that Object Oriented (OO) programming offer you. Typically, I don’t have many occasions to go this route using EFQs.

Looking for quality Drupal Web Hosting? Look no further than Arvixe Web Hosting!

Tags: , , , , , , , , , , , | Posted under Drupal | RSS 2.0

Author Spotlight

David Gurba

David Gurba

I am a web programmer currently employed at UCSB. I have been developing web applications professionally for 8+ years now. For the last 5 years I’ve been actively developing websites primarily in PHP using Drupal. I have experience using LAMP and developing data driven websites for clients in aviation, higher education and e-commerce. If you’d like to contact me I can be reached at david.gurba@arvixe.com

Leave a Reply

Your email address will not be published. Required fields are marked *


+ 7 = 12

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>