EFQ has more than 60 tests showing a lot of usage. Is that enough example? Do we want a module too?

Files: 
CommentFileSizeAuthor
#52 examples-916776-52-efq_example.patch16.96 KBeojthebrave
PASSED: [[SimpleTest]]: [MySQL] 2,693 pass(es).
[ View ]

Comments

rfay’s picture

Examples are for teaching and tests are for testing. While they sometimes have common ground, if we need to teach people EntityFieldQuery, we probably need an example. Could we get it into the proposed Entity Example?

chx’s picture

Status:Needs review» Active

A module exposing an entity will be somewhat rare while EntityFieldQuery will be abudant. http://drupal4hu.com/node/267

ilo’s picture

Perhaps this is a good case to mix with nodeapi_example.. The purpose of the nodeapi_example is to show the hooks of node API. Currently we are doing this using a module similar to rating (iirc) that adds information to a node. Chx, you suggested to change that module and also use fields (as node_example module does), but we do already have a field_example module showing how to use fields, and I agree with rfay that we don't need to rewrite again that part.

However, to teach the usage of the node API hook, I see no reason why we can't use a custom entity instead of a field. There is no reason to mimic current functionality (the intention of the module is to show the hooks), that would fix two problems at once..

What do you think?

rickvug’s picture

I can say that examples would be helpful. I'm currently struggling with how to find all nodes that have the tid "2" attached via the field "country_from". The code that I have is as follows:

$query = new EntityFieldQuery;

$result = $query
  ->entityCondition('entity_type', 'node')
  ->propertyCondition('status', 1)
  ->fieldCondition('country_from', 'value', 2, '=')
  ->execute();

Hopefully this helps give an idea of where people will get hung up.

rickvug’s picture

For the record, my problem was silly - looking for 'value' rather than 'tid'. Really liking EntityFieldQuery. Will have to continue to explore it.

rfay’s picture

@rickvug, an example is welcomed, if you beat @chx to it :-)

But please do post your successful code here for others.

chx’s picture

@rickvug if that's a problem then a core patch detailing more how column is not always value would be good.

q0rban’s picture

Subscribe, this would definitely be helpful. I'm currently trying to figure out how to do an "OR" select on an entity, for instance in finding a user whose init or mail column contains a specific email address, but it doesn't seem like that is possible.

the greenman’s picture

Here is my lesson. Despite reading the docs on the fieldquery object, I completely misunderstood the purpose of the delta group.

I have not seen any other examples for this yet, so, I'll post this here so that we can add it to any example produced.

In this example, I am working with the new organic groups, and need to select all group members with a specific state. If I do not add the delta_group, the SQL produced does not connect the gid and state portions of the query.

Delta groups allow you to define dependent sets of criteria - pretty important.

$query = new EntityFieldQuery;
  $query
    ->entityCondition('entity_type', 'user')
    ->fieldCondition('group_audience', 'gid', $gid, '=', 0);
  if (!is_null($states)) {
    $query
      ->fieldCondition('group_audience', 'state', (array) $states, 'IN', 0);
  }
  $users = $query->execute();
electblake’s picture

subscribing - I'm always a code example sort of guy. Although I can sift through the code and dive and find what I need (which eventually gets the job done) having code examples (like the ones I found on this page) saves me a lot of time.

Sylvain Lecoy’s picture

Version:7.x-1.x-dev»

Here is a simple example to load up some nodes of type event for the month of March, looking up information of a field type datetime called 'field_date':

<?php
  $query
= new EntityFieldQuery();
 
$entities = $query->entityCondition('entity_type', 'node')
                    ->
entityCondition('bundle', 'event')
                    ->
propertyCondition('status', 1)
                    ->
fieldCondition('field_date', 'value', array('2011-03-01', '2011-03-31'), 'BETWEEN')
                    ->
fieldOrderBy('field_date', 'value', 'ASC')
                    ->
execute();

 

$nodes = node_load_multiple(array_keys($entities['node']));
 
$views = node_view_multiple($nodes, 'teaser');
 
$build['#nodes'] = $views['nodes'];
 
$build['#theme'] = 'whatever';

  return

$build;
?>
electblake’s picture

thanks! really touches on so many of the mechanics in a sample use-case :) great share.

s1l’s picture

Version:» 7.x-1.x-dev

thanks for this, the examples helped me out a lot.

I've combined the #11 example with the if and the entity_load from
http://www.commerceguys.com/resources/articles/183

My usecase was that I searched for a node with field_yourfield = 123, and I wanted to do something with the value of another field (field_yourotherfield) of that node. Not sure if this helps this issue, but I hope people searching for a complete example find this usefull.

$yourvalue = '123';
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'yournodetype')                   
->fieldCondition('field_yourfield', 'value', $yourvalue, '=')
->fieldOrderBy('field_yourfield', 'value', 'ASC');
   
$entity_type = 'node';
$result = $query->execute();

if (!empty($result[$entity_type])) {
$entities = entity_load($entity_type, array_keys($result[$entity_type]));
}

$nodes = entity_load('node', array_keys($result['node']));
foreach ($nodes as $node) {
   print $node->field_yourotherfield[LANGUAGE_NONE][0][value];
}

Edit by chx: changed und to LANGUAGE_NONE. Also note that http://api.drupal.org/api/drupal/modules--field--field.module/function/f... is more appropriate than LANGUAGE_NONE

anglo’s picture

How about alternative conditions? I need to get fields with '1' value, then with '2 value'. Then I need the same with status '0'. How not to duplicate the following code:

$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'yournodetype')                  
->fieldCondition('field_number', 'value', '1', '=');

$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'yournodetype')                  
->fieldCondition('field_number', 'value', '2', '=');

Sylvain Lecoy’s picture

We need a sample using a custom pager as well: see my support request #1179180: Custom pager for an EntityFieldQuery ?.

jjmontgo’s picture

Version:» 7.x-1.x-dev

How do you query nodes with a title which contains "blah" OR (not and, or) a body that contains "blah"?

There doesn't seem to be any examples of boolean conditions ANYWHERE?

Example:

// results in AND conditions not OR
$q = new EntityFieldQuery();

$q->entityCondition('entity_type', 'node')
->propertyCondition('type', 'page')
->propertyCondition('status', 1)
->propertyCondition('title', 'blah', 'CONTAINS')
->fieldCondition('body', null, 'blah', 'CONTAINS')
->pager(20);

m4olivei’s picture

All of the examples so far suggest that you query for an entity using EntityFieldQuery and then call entity_load() on the result. In my case all I want to do is to list nodes of a specific type ordered by the value of a field. It seems like its overkill to have to node_load all the nodes returned from such a query when all I really need is the nid, title, and value of the ordering field. Is there a way to get EntityFieldQuery::execute() to return more than just nid, vid, and type to avoid a node_load?

q0rban’s picture

Title:Do we need an EntityFieldQuery example?» Add an EntityFieldQuery example
krimos’s picture

Is there an example for how to display my EntityFieldQuery results in a block.
Can i use theme('search_results') ?

hutch120’s picture

Nice write up @s1l, small code correction (for #13).
This:

print $node->field_yourotherfield[und][0][value];

Should be:

print $node->field_yourotherfield['und'][0]['value'];
chx’s picture

Neither , it should be print $node->field_yourotherfield[LANGUAGE_NONE][0]['value']; fixed there.

restyler’s picture

I would recommend

<?php
entity_metadata_wrapper
('node', $node);
print
$node->field_yourotherfield->value();
?>

to avoid issues with languages (Entity module required)

chx’s picture

I strongly recommend against requiring entity module for a core example.

rfay’s picture

While I strongly support the creation and maintenance of an entity_api_example module that demonstrates how to use Entity module, it will not be used here. This project is for core examples. Have to draw the line somewhere. These examples can contain links to others...

yakoub’s picture

@m4olivei

All of the examples so far suggest that you query for an entity using EntityFieldQuery and then call entity_load() on the result. In my case all I want to do is to list nodes of a specific type ordered by the value of a field. It seems like its overkill to have to node_load all the nodes returned from such a query when all I really need is the nid, title, and value of the ordering field. Is there a way to get EntityFieldQuery::execute() to return more than just nid, vid, and type to avoid a node_load?

i think the problem of what you are suggesting is that without entity_load then the field type specific load hooks are not run , for example text_field_load .

also by inspecting the entity_load process i found there is persistent cache handling in field_attach_load although hook_field_storage_load() seems to be invoked either way so i don't understand how it works .

moreover instead of entity_load you could call field_attach_load directly and use 'options' parameter to load only single field and not the whole object .

in the end you should always use pager, so for each page you display few entities and calling entity_load 10,20 times is not a big deal .
if you are building an application which should display 100 entities on single page, then you should consider providing your own cache management class to optimize for your needs .

also consider that given entities are cached, then doing an sql join to the field table could turn out redundant and even worst performance than calling entity_load for each entity .
also if you pass entity_load an array of ids, then it will end up using the 'IN' operator , in other words there will be a single query per field type to load the values for all entities at once

adrianmak’s picture

I tried this snippet of code

$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
  ->propertyCondition('status', 1)
$result = $query->execute();

but it just returned me a blank page.

yakoub’s picture

you need to ->fetch()

chx’s picture

No you dont you need to add a range first then load and iterate the results like

<?php
if (!empty($result['node'])) {
 
$nodes = entity_load('node', array_keys($result['node']));
  return
node_view_multiple($nodes);
}
?>
timcosgrove’s picture

https://github.com/timcosgrove/efq_example

I had written this a few months ago as part of a blog post I was going to write, which didn't happen. i'd be happy to spruce it up and submit it, if people think it would be useful.

Basically it installs 3 content types and provides a couple of example callbacks and a block which demonstrate basic EFQ usage.

It was in no way created with any Drupal core Example module standards in mind. If the module seems useful to people but is not in line with standards I can do that if I'm pointed towards guidelines.

Mile23’s picture

Well, 1) You could make it a drupal.org sandbox project. :-)

2) Install Coder and run it on this module in strict mode. It looks pretty reasonable as-is, but there are some things like whitespace issues and so forth.

3) Have a look at some of the other examples, to see the basic doxygen commenting format. You want to explain stuff in the doxy blocks, so there's something good to read on api.drupal.org when it finally gets committed. This would include lots of @see directives, so it's easy to cross-link to the Drupal api pages.

4) More meaty comments. For instance, it seems obvious that we're 'setting up some basic parameters' here. What do the specific lines do?

  // set up some basic parameters
  $query
    ->entityCondition('entity_type', 'node')
    ->entityCondition('bundle', array('efq_article', 'efq_page', 'efq_photo'))
    ->propertyCondition('status', 1)
    ->propertyOrderBy('created', 'DESC');

5) Tests.

6) If all of this is too much, do any of the above and make a patch and add it here. Others can work on it, too.

I haven't installed it, but it looks useful. Good work. :-)

rfay’s picture

ralphb’s picture

As someone who struggled considerably migrating my modules to Drupal 7 I think that EFQ examples would be extremely helpful.

With all the hoopla about fields in D7, plain queries using db_query or db_select are becoming increasingly useless. Just take one of the most basic use cases imaginable: A report-style list of nodes of a particular type with custom-added fields in a table with paging and sorting. I could not find a single example on the Web that covers that case. The existing example modules tablesort_example and pager_example aren't very helpful, as queries using db_select and EFQ have inconsistent APIs.

As chx suggested I was able to piece together enough information from the D7 source and the entity_query test cases eventually, but reverse-engineering the API from that isn't particularly user-friendly.

jphil’s picture

Can anyone show me the syntax (if it is possible) for stating a disjunction (i.e. this OR this) for a fieldCondition? I'm starting to miss the raw power of SQL. I love writing joins, my brain gets off on it. Tell me I can do a disjunct with EFQ... please.

chx’s picture

Assigned:chx» Unassigned
keshavulu4u’s picture

hi

$query->join('field_data_field_amountpaid', 'amt', 'n.nid = amt.entity_id and amt.field_amountpaid_value >=500 and amt.field_amountpaid_value <=5000 '); //JOIN node with Body

this is my normal query how can i call the in the enttiy query

i try this way

$query->fieldCondition('field_amountpaid', 'value', array('501','5000'),'BETWEEN');

but it's not working. any idea.

g76’s picture

I have a code snippet for rules, but it is for drupal 6. It's for loading the nid of a referenced node, getting it's menu item and then adding the original node as a child menu item. I am not a coder and am unsure how to do this for D7. If anyone could provide a snippet for D7, I would be in your debt:). I have the code for just creating a new top level parent menu item for D7, but not the rest.

// Get the referenced node's nid
$nid = $node->field_noderef[0]["nid"];

// Get the menu item linking to it
$row = db_fetch_array(db_query("
  SELECT mlid
  FROM {menu_links}
  WHERE link_path = 'node/%d'
  AND menu_name = '%s'
"), array($nid, 'primary-links'));

// Set it as the parent for the new menu link
$item = array(
  'link_path' => 'node/' . $node->nid,
  'link_title' => $node->title,
  'plid' => $row["mlid"],
  'hidden' => 1
);
menu_link_save($item);

tylerfrans’s picture

I tried to use EntityFieldQuery for the first time, but kept getting the following error:

Fatal error: Call to undefined function field_read_fields() in modules/field/modules/field_sql_storage/field_sql_storage.install on line 16

I'm just trying to get it to work, so in my module I have the following:

$query = new EntityFieldQuery();
$result = $query->entityCondition('entity_type', 'node')
->propertyCondition('status', 1)
->execute();

Any thoughts on what may be causing the error?

Edit: My issue was that I was calling this before the proper functions had been loaded. Using it in a real scenario with a hook worked.

adrianmak’s picture

@tim.cosgrove

from your efq_example module info
image and list modules are dependcies modules, which are these two modules acutally ?

adityamenon’s picture

#11 is excellent. For those who want to look at more code, check this out...

adityamenon’s picture

There's an example uploaded to GitHub for EntityFieldQuery: https://github.com/timcosgrove/efq_example.

yakoub’s picture

@adityamenon is spamming with the efq_example stuff .

rfay’s picture

@yakoub, certainly not. It's always valuable to post relevant information in an issue. And you should look up the definition of "spam".

It does look like @adityamenon posted twice when he only meant to post once. That's happened to me a time or two as well, due to connectivity or d.o problems.

rajiv.singh’s picture

How can we select the nodes created by particular month (ex: January 2012).
Can anybody please guide to use data granularity on fieldCondition.

avadhutp’s picture

@phpsrajiv: Here's how I'd do it:

$eQuery = new EntityFieldQuery;
$eQuery->entityCondition('entity_type', 'node') //Set the type of entity to retrieve
->propertyCondition('status', 1) //You want to retrieve only active files
->propertyCondition('created', array(mktime(0, 0, 0, date('n'), 01, date('Y')), mktime(0, 0, 0, ((date('n')) + 1), 0, date('Y'))), 'BETWEEN') //Only for the current month, you could modify this line to your heart's extent

$fileUsage = $eQuery->execute();

avadhutp’s picture

Recently, in one of my projects, the use case was that we had to display the number of PDF files the currently logged in user generated in the current month:

$eQuery = new EntityFieldQuery;
$eQuery->entityCondition('entity_type', 'file') //Set the type of entity to retrieve
->propertyCondition('uid', $user->uid) //Set the current user's UID
->propertyCondition('status', 1) //You want to retrieve only active files
->propertyCondition('filemime', 'application/pdf') //The file type is PDF
->propertyCondition('timestamp', array(mktime(0, 0, 0, date('n'), 01, date('Y')), mktime(0, 0, 0, ((date('n')) + 1), 0, date('Y'))), 'BETWEEN') //Only for the current month
->count(); //Give me only the count; redact this line if you need all FIDs

$fileUsage = $eQuery->execute();

drm’s picture

What if I want to load the values in a certain field based on the query, but not the entire node in the set? I've a situation with very large and complex nodes that take a long time to load and I often want to pull out just one or two values from each node, and maybe the nid.

RavindraSingh’s picture

Does EntityFieldQuery works in Drupal 7? if yes please tell me how to use it.

HongPong’s picture

not to veer too far from the thread but - @it.ravindrasingh here's a main bit of documentation http://drupal.org/node/1343708 - there are other tutorials on 3rd party sites.

mabho’s picture

Thank you so much for sharing this, s1l, really, really useful. It saved me a good time.

mkadin’s picture

As a note to those following this issue, there's a challenge on The Module Off that calls for an EntityFieldQuery example. If you have a working example of how to use EntityFieldQuery, you may want to submit it for a chance at the prize.

Better hurry though, there's only 2 days left in the challenge!

Either way, I'll work with the winner of the current challenge to submit their module as a patch on this issue.

Mile23’s picture

Great, mkadin. Looking forward to a patch. :-)

eojthebrave’s picture

Component:Other» Entity Example
Category:task» feature
Status:Active» Needs review
StatusFileSize
new16.96 KB
PASSED: [[SimpleTest]]: [MySQL] 2,693 pass(es).
[ View ]

I've been working through a bunch of this prepping to do some training videos for drupalize.me and ended up taking a bunch of notes and writing a bunch of examples. Here's what I've got thus far. It covers a majority of things at least on the surface.

The one caveat here is that this example assumes that you've got a field named 'field_number' that is an INT field and is attached to both the 'user' and the 'article' bundles in order to demonstrate using EFQ across multiple entity types. We should probably write an hook_install that adds this field.

You'll also likely want to generate a bunch of dummy data with devel so the examples have something to query. However, even without that the code should be helpful.

Mile23’s picture

Super ultra awesome documentation. Except it doesn't quite fit the Examples format... It needs a bunch of docblock formatting to be readable through api.drupal.org.

Also I'm not sure it should be a patch to entity_example, since it doesn't actually use entity_example_basic. Splitting it up into entity_example.efq.inc helps, but we're trying to keep things as simple per module as we can.

Very good stuff tho. Also unicorns.

Mile23’s picture

Status:Needs review» Needs work
eojthebrave’s picture

Do you want split it up in to a bunch of smaller functions with docblock for each one? Or are you just referring to the big comment at the top of the file? I'm not aware of any docblock syntax for inline comments which is what most of this is.

I agree, it does feel a bit weird having it be part of the entity_example module though that's what was referenced earlier in the thread so I had just put it there for now.

Mile23’s picture

So first of all, with the docblocks:

Start with the Drupal doxygen standards: http://drupal.org/node/1354

Each example is its own doxy group, so everything has to belong to it (all functions, all files): http://drupal.org/node/1354#defgroup

For each function we'd have a function-level docblock with an explanation of what's happening, and then inline comments would clarify what's unreadable about the code.

The goal of all this is so that we can pull it into api.drupal.org, like this: http://api.drupal.org/api/examples/field_permission_example%21field_perm...

Then it has to have a test. :-)

iampuma’s picture

Example with multiple node view and pager

<?php
 
$output
= array();

$query = new EntityFieldQuery();
$query->entityCondition('entity_type','node')
  ->
pager(5);
  ->
execute();

if (isset(
$result['nodes'])) {
 
$content = node_view_multiple(node_load_multiple(array_keys($results['nodes'])));
 
$output = array(
   
'content'=> $content,
   
'pager'=> array(
     
'#markup'=> theme('pager'),
     
'#weight'=>10
   
));
}

return
render($output);
?>
yakoub’s picture

i think it is poor readability to make this nested function calls on one long line :

<?php
$build
= array();
$nodes = node_load_multiple(array_keys($results['nodes']));
$build['content'] = node_view_multiple($nodes);
$build['page'] = array('#theme' => 'pager');
return
$build;
?>

and render is suppose to happen only in template file so that the render array can be altered by others

Johann Wagner’s picture

#22
If this uses much more memory, it should be avoided.

Like said #17, there should be a way to get more than nid, vid and type from the request, then it would be really useful.

Alan D.’s picture

Same as #59, this would be great to get select lists, etc if the label property could be hooked into the query. Anyone searched core for any corresponding issues related to this?

Alan D.’s picture

Doesn't look like this is possible in D7 or D8 :(

Guess 2 queries is better than constantly handling this yourself.

Simple node query example to get report content types where published an having a specific field value on Status (field_status) set to active.

<?php
    $options
= array();
   
$query = new EntityFieldQuery();
   
$query->entityCondition('entity_type', 'node', '=')
      ->
entityCondition('bundle', 'report', '=')
      ->
fieldCondition('field_status', 'value', 'active')
      ->
propertyCondition('status', 1)
      ->
addMetaData('account', user_load(1));
   
$result = $query->execute();
    if (
$result && !empty($result['node'])) {
     
$options = db_select('node', 'n')
           ->
fields('n', array('nid', 'title'))
           ->
condition('nid', array_keys($result['node']))
           ->
orderBy('title')
           ->
execute()
           ->
fetchAllKeyed();
    }
?>
dozymoe’s picture

#60 IIRC there is hook to override entity label, so entity label is not necessary be the entity's label database field though.
Does entity_cache module help with the entity_load() issue?

Alan D.’s picture

@dozymore
Yep, that is correct but if the title is a base property, as per revision id, having it in the results would be nice. Complicated by i18n issues here which is probably driving people away from looking at it :/

Yes, caching should help, http://www.lullabot.com/blog/articles/module-monday-entity-cache, but my own benchmarking on one non-core entity showed no statistical relevant benefit. This was on the country entity and would be most likely due to db level caching on a finite entity list, 200ish, so large numbers of nodes, users, you should see benefits, on small regularly used ones, the benefits are likely minimal.

drupalshrek’s picture

Issue summary:View changes

I wanted to get a list of all nodes of a particular content type. My first try was:

<?php
  $query
= new EntityFieldQuery;
 
$result = $query
   
->entityCondition('entity_type', 'my_content_type')
    ->
execute();
 
dsm($result);
?>

The correct code I soon found is as follows. Content type name is of course effectively bundle name.

<?php
  $query
= new EntityFieldQuery;
 
$result = $query
   
->entityCondition('entity_type', 'node')
    ->
entityCondition('bundle', 'my_content_type')
    ->
execute();
 
dsm($result);
?>
Alan D.’s picture

If you want to include extended class examples, a fetch all and simple factory method is a must imho.

<?php
// List of all terms in a vocab with the machine name 'region'.
$terms = GloTermFieldQuery::create('region')->fetchTerms();
?>
<?php
class GloTermFieldQuery extends EntityFieldQuery {
 
/**
   * Simple factory method to generate GloTermFieldQueryobjects.
   *
   * @return GloTermFieldQuery
   *   The called object.
   */
 
public static function create($bundle = NULL, $order = 'weight', $direction = 'ASC') {
   
$efq = new GloTermFieldQuery($bundle, $order, $direction);
    return
$efq;
  }

  public function
__construct($bundle = NULL, $order = 'weight', $direction = 'ASC') {
   
$this->entityCondition('entity_type', 'taxonomy_term');
   
// The bundle(s).
   
if (isset($bundle) && ($vocab = taxonomy_vocabulary_machine_name_load($bundle))) {
     
$this->propertyCondition('vid', $vocab->vid);
    }

   
// Default order.
   
if (isset($order)) {
     
$this->propertyOrderBy($order, $direction);
    }

  }

  public function
fetchTerms() {
   
$results = $this->execute();
    if (!empty(
$results['taxonomy_term'])) {
      return
taxonomy_term_load_multiple(array_keys($results['taxonomy_term']));
    }
    return array();
  }

}
?>
yakoub’s picture

this is not a factory :

<?php
new GloTermFieldQuery
?>
Alan D.’s picture

year, not sure if that has a proper oo pattern name, but saves a lot of typing ;)