Previously we have been able to turn off entity caching by using either hook_entity_type_alter() or hook_entity_type_build() by doing the following:

/**
 * Implements hook_entity_type_alter().
 */
function MY_MODULE_entity_type_alter(array &$entity_types) {
  $entity_types['ENTITY_TYPE_ID']->set('static_cache', FALSE);
  $entity_types['ENTITY_TYPE_ID']->set('persistent_cache', FALSE);
  $entity_types['ENTITY_TYPE_ID']->set('render_cache', FALSE);
}

This process no longer works in 8.7.x or 8.8.x since the introduction of entity type definitions now having the ability to be "loaded from code" and also the ability to get "the active definitions" in issue 2554235: Make the content entity storage and entity query use the last installed definitions instead of the ones living in code

The issue now is that depending on how the entity type object is retrieved, we will get different results.

For instance if we want to just turn off persistent caching on nodes, we would do the following:

/**
 * Implements hook_entity_type_alter().
 */
function MY_MODULE_entity_type_alter(array &$entity_types) {
  $entity_types['node']->set('persistent_cache', FALSE);
}

But this will not turn off persistent caching for nodes, as the following would indicate.

/** @var \Drupal\Core\Entity\EntityTypeManager $entity_type_manager */
$entity_type_manager = Drupal::service('entity_type.manager');
// The node's entity type when loaded "from code".
$is_cachable_1 = $entity_type_manager->getDefinition('node')->isPersistentlyCacheable();
// The node's entity type when loaded "from active".
$is_cachable_2 = $entity_type_manager->getActiveDefinition('node')->isPersistentlyCacheable();

// The node storage's entity type object is loaded "from active".
$is_cachable_3 = $entity_type_manager->getStorage('node')->getEntityType()->isPersistentlyCacheable();

// Node is ultimately loaded from persistent cache (if previously loaded)
// since load() uses the entity type object from the SqlContentEntityStorage
// class. This can be proven to load from cache by putting a breakpoint
// in \Drupal\Core\Entity\Sql\SqlContentEntityStorage::doLoadMultiple().
$node = Node::load(1);
// Yet the loaded node's entity type object is loaded "from code".
$is_cachable_4 = $node->getEntityType()->isPersistentlyCacheable();

// Results:
// $is_cachable_1 === FALSE
// $is_cachable_2 === TRUE
// $is_cachable_3 === TRUE
// $is_cachable_4 === FALSE

Is there an official way to modify an existing entity type to disable caching (or perform other modifications) besides using hook_entity_type_alter() or hook_entity_type_build()?

Comments

mdolnik created an issue. See original summary.

mdolnik’s picture

Note: A temporary work-around could be achieved by calling EntityLastInstalledSchemaRepository::setLastInstalledDefinition() in the entity-type-alter hook after modifying the entity type...

/**
 * Implements hook_entity_type_alter().
 */
function MY_MODULE_entity_type_alter(array &$entity_types) {
  $entity_types['node']->set('persistent_cache', FALSE);

  /** @var \Drupal\Core\Entity\EntityLastInstalledSchemaRepository $entity_last_installed */
  $entity_last_installed = \Drupal::service('entity.last_installed_schema.repository');
  $entity_last_installed->setLastInstalledDefinition($entity_types['node']);
}

But I don't think this is the best way to go about getting the hook_entity_type_alter() approach to work, as this is skirting the entity type alter process by manually updating the latest installed definition.

If anything I beleive the entity-type-alter process itself should be doing this behind the scenes in core after all of the entity-type-alter hooks are called and prior to caching the built definitions.

Thoughts?

alexpott’s picture