When trying to load all of the entities of a certain type (e.g. entity_load('user') or something) within the same set of transactions, the second time that the function is called, no results are returned. This is because the cacheGet function has an elseif($conditions) which needn't be there (sometimes you really are requesting all of the entities, so no $ids or $conditions need be present. This is even indicated by the conditions argument being optional). Removing the elseif and replacing it with an else prevents this edge case from occurring.

This issue was discovered in #1542824: entity_load calls in hook_menu only work for the first implementation, but was determined to be core rather than Entity API.

Comments

Status: Needs review » Needs work

The last submitted patch, entity-entity_remove_elseif_from_caching-1542824-2.patch, failed testing.

ankur’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, entity-entity_remove_elseif_from_caching-1542824-2.patch, failed testing.

johnv’s picture

Status: Needs work » Needs review
johnv’s picture

Title: DrupalDefaultEntityController::cacheGet does not load entity cache when accessing all entities » DrupalDefaultEntityController::cacheGet returns no result (on second call, when loading all entities)
Priority: Normal » Major
Issue summary: View changes

Marked the two 'child issues' #1823926 and #1542824 as duplicates.
Moved this issue to 'major', since this this is a sneaky WTF when developing custom entities.
There doesn't seem to be a more 'local' solution in Entity module.

ATM, it seems every custom entity now needs to implement the following advice from #1542824-6: entity_load calls in hook_menu only work for the first implementation

I had the same issue, but used drupal_static() to save the result for the duration of pageload. See the first example here: http://www.lullabot.com/blog/articles/beginners-guide-caching-data-drupal-7

johnv’s picture

And this is my solution in custom code:

/**
 * Implements a controller class for MyEntity.
 */
class MyEntityController extends EntityAPIController {

  /**
   * Overrides DrupalDefaultEntityController::cacheGet()
   */
  protected function cacheGet($ids, $conditions = array()) {
    $entities = array();
    // Load any available entities from the internal cache.
    // Override default function, due to core issue #1572466.
    if ($ids === FALSE && !$conditions) {
      return $this->entityCache;
    }

    return parent::cacheGet($ids, $conditions);
  }
}
johnv’s picture

OTOH, (regarding the 'major' status). It might be better NOT to resolve this problem in D7, since new contrib's will get strange issues in the queue, that are dependent on the D7-version of the user and the D7-version of the contributor when developing the module.

Status: Needs review » Needs work

The last submitted patch, entity-entity_remove_elseif_from_caching-1542824-2.patch, failed testing.

berdir’s picture

Without entity.module's $all_loaded flag, your code isn't correct, it will just return all entities that it has currently loaded, which don't have to be all that exist.

johnv’s picture

You mean like this:

    if ($this->cacheComplete && $ids === FALSE && !$conditions) {
      return $this->entityCache;
    }

I've tested with a db of 15 custom entities, with the following in any order in 1 page request, and got perfect results, unless I do unset($this->entityCache[5]) deliberately in between.

entity_load_multiple(array(1,2,5));
entity_load_multiple(array(2,5,6));
entity_load_multiple();
entity_load_multiple();

But adding it doesn't hurt either, and is more in sync with Entity's code.

pieterdc’s picture

Status: Needs work » Closed (duplicate)

Thanks for the report paulmarbach but #1273756: Allow DrupalDefaultEntityController::cacheGet() to return all cached entities was earlier.
So, I'm closing this issue as a duplicate of that issue.

And thanks johnv for the non-intrusive workaround you shared at #1572466-6: DrupalDefaultEntityController::cacheGet returns no result (on second call, when loading all entities).
And thanks Berdir for your feedback, but the $all_loaded flag has gone...