Problem/Motivation
Entity storage controllers allow you to retrieve and save data on multiple tables, but entity query's SQL back end does not support the same. This limits the flexibility of extending entities with swappable entity storage controllers. We have run into this problem trying to port our contrib module to drupal 8.
Context
The specific thing we are working on is allowing an Anonymous User API where we create the separation between People and Accounts as talked about in #1806514: Unify anonymous and registered users. Swappable entity storage controllers allow us to leave account information in the users
table and introduce a new table for people who may or may not have an account.
The storage controller deals with saving to both tables and retrieving the information via a join. However, entity queries break when trying to add a condition on a property of a joined table as Drupal\Core\Entity\Query\Sql\Tables::ensureEntityTable()
is hard-coded to the base table and data table from the entity info.
To solve this, I thought I could override Tables
with a specific one for my entity. However, Tables
is a hard-coded class name in numerous places, meaning the only way to do that would be to the:
- Override
Drupal\Core\Entity\DatabaseStorageController::getQueryServiceName()
to use a differentQueryFactory
- Override
Drupal\Core\Entity\Query\Sql\QueryFactory::get()
andDrupal\Core\Entity\Query\Sql\QueryFactory::getAggregate()
to use differentQuery
andQueryAggregate
classes... - Override
getSqlField()
in bothQuery
andQueryAggregate
so that they use our newTables()
class - Override the entirety of
compile()
in bothCondition
andConditionAggregate
- And I haven't even looked to find all the places I would need to override to get it using the correct
Condition
andConditionAggregate
While this route would should work, it is not "Don't Repeat Yourself", requires lots of contrib code and diminishes DX.
Proposed resolution
I have thought of a couple approaches that could make this whole thing a bunch easier:
A) Allow entity definitions or storage controllers to specify/return the Tables
implementation:
This would allow contrib developers to override anything they need to in Tables
to match whatever they are doing.
B) Allow additional tables to be included in the entity info the same way that data_table
is:
This would be a much simpler change, but allow lots of flexibility for contrib developers to store information across multiple tables if required.
API changes
Depending on approach, probably either some additional information in the entity definition or an additional method on the storage controller. In either case, they would only need a developer to do anything if they want to do something different to the default behavior.