EntityFieldQuery: Let Drupal Do The Heavy Lifting (Pt 1)

Drupal 7 introduced the EntityFieldQuery API. This class is a mechanism for quickly building queries of entities and fields – typically nodes, but of course not limited to that.

Drupal 7 features a much richer database abstraction layer than previous versions of Drupal, but in the end you are still more or less building SQL. EntityFieldQuery allows you to construct queries without much knowledge of SQL at all.

Drupal core itself mostly uses EntityFieldQuery as a utility function, in many cases simply to check that a given field has a value somewhere in the system or not. It’s strange that such a powerful mechanism is put to so little use by core, but no matter. Let’s see how we can use it.

Starting Your Query

Starting an entity field query looks like this:

Extremely simple, right? That’s all it takes to get started. Let’s now add some conditions to our query.

Let’s take a look at what’s going on here. First of all, notice the lack of semicolons between method calls. Each EntityFieldQuery method returns the same EntityFieldQuery object the method is called on. This allows us to chain method calls together, which speeds up coding and makes it easier to read. This will look familiar to anyone who uses jQuery. This could just as easily be written like so:

But, that is really not easy at all to read. I recommend putting each method on its own line. Future generations of coders will thank you.

Now let’s look at each method and see what’s happening.

The first method uses an entityCondition to tell the query to look for node entities. It may seem like specifying this is redundant, but as many other things in Drupal 7 are also entities – users, taxonomy terms, etc – you need to restrict your set.

The second method tells the query which node types to restrict the set to. This can be left out if you would like to query all available nodes, but in most cases you will be looking for specific node types. Note also that the second argument, ‘article’ in this case, can be either a string or an array; the query will adjust automatically. So if you were looking for both article and page node types, you could rewrite that part of the chain as follows:

As you can see, it’s extremely easy to expand your query.

The third method is a propertyCondition. A property in this case is any column in the base table for the given entity type. In the case of nodes, this could be whether it is published, the user that created the node, time of creation, etc. In our example above, we are modifying our query to only return published values.

The last method in our example above uses propertyOrderBy to set an order. In this case, we’re simply asking for the results to be returned in reverse chronological order.

Querying Fields and Limiting

Now let’s add a query on a field value using a fieldCondition. Let’s assume each of the node types in our example has a field ‘field_us_state’ assigned to it. We’re going to find nodes that are associated with the New York Tri-state area, which also includes Connecticut and New Jersey. This would look like this:

We can order by field values as well, if that is useful to us. Note that ordering conditions are processed in the order that they are added to the query.

Perhaps for our purposes, we want to limit our query to the 10 most recent items. Let’s add a range:

Et Voilà

Finally, we execute the query and assign that to a variable:

This returns us an array of entity ids that match the conditions specified for the query. If we are querying nodes, the information will be under $result['node']. In most cases, what you actually want are the nids that have been returned. This is easily accomplished:

Putting that all together, we have:

This is not very much code at all for this result. Moreover, we don’t need to know anything about SQL or even about the underlying storage engine being used. We simply write the query in this simple syntax, and EntityFieldQuery API does the job of translating that into a query that Drupal’s database abstraction layer understands and executes it for us.

What would we do with this list of nids? Pretty much anything. We might load them, for starters:

We might want to display these 10 nodes in a teaser style. That’s also easily done. Let’s generate a Drupal render array:

More To Come

This is just the beginning. Look for part 2 of this post, where we will show more concrete examples of putting EntityFieldQuery to use. Also look out for posts from other Treehouse engineers explaining more advanced topics related to EntityFieldQuery.

  • http://twitter.com/kid_ic4rus Ryan Kois

    Seriously? 0 Comments? Thank you, Tim, for putting this together. EFQ is a crucial mechanism to grasp.

  • Bruce C hotwebideas.net

    Hey, great tutorial on EFQ. I was driving myself crazy trying to do the same thing with a Drupal view w/ contextual filters and the views_get_view() function and nothing worked. EntityFieldQuery() is both the easiest and the most powerful. Thanks!. I am waiting for Part 2.

  • jayboss222

    This is solid! Great breakdown of an amazing function. Thanks for providing some great insight into an ill documented class

  • John

    Great post, I am just learning to code for Drupal and your post is easy to follow and understand, Thank you!

  • Animad9

    Drupal and disqus same with wordpress anf disqus?

    Fairbanks SEO

  • analogymous

    Great article, it is well written and gets the point across wonderfully.

    I have two issues. Could you pre format your code; It is difficult to read. Also, you are using ‘ (apostrophe) in the article instead of ‘ (single ditto mark). I was attempting to run your code in devel and it kept giving me an error. I could not see why until I copied it over to my IDE.

    • Tim Cosgrove

      Thanks Frank! This post needed some code formatting attention. Hopefully this will help both your problems.

      • analogymous

        Beautiful, thanks.

  • http://www.seduniatravel.com/ Steven Wong
  • Pingback: Phase2: Static Prototyping and Keeping Drupal Simple (KDS) - Drupal King

  • Chris

    Great article. I learned a lot about EFQ here.. I am just wondering
    if I could add a condition based on a custom field in the user
    profile… I.e. query articles created based on that custom field.

    thanks!

  • federico

    This is really interesting. Is it possible to get also other infos from the nodes without calling a node_load on the nids?
    for example, i’d like to have the title of the nodes retrieved, and i just need that. Can i avoid calling node_load_multiple to get that information?
    thanks!