Come together with the global Drupal community in Rotterdam, 28 Sept – 1 Oct 2026. Sessions, contribution, connection, and Early Bird savings until 8 June.
I can't see anything wrong with this, but views isn't really my area of expertise.
Is it worth pinging someone else on VDC to give this a once-over?
If not, RTBC+1
Ok we have an issue now. I have been adding and extra condition to join which checks target type of current relationship. It works fine for single relationship but for multiple relationships join produce no result because a single value can't have two values of target types as can be seen in the resultant query.
SELECT entity_test.id AS id, entity_test_entity_test__field_test.id AS entity_test_entity_test__field_test_id, entity_test_mul_property_data_entity_test__field_test.id AS entity_test_mul_property_data_entity_test__field_test_id
FROM
`entity_test` entity_test
LEFT JOIN `entity_test__field_test` entity_test__field_test ON entity_test.id = entity_test__field_test.entity_id AND entity_test__field_test.deleted = '0'
INNER JOIN `entity_test` entity_test_entity_test__field_test ON entity_test__field_test.field_test_target_id = entity_test_entity_test__field_test.id AND entity_test__field_test.field_test_target_type = 'entity_test'
INNER JOIN `entity_test_mul_property_data` entity_test_mul_property_data_entity_test__field_test ON entity_test__field_test.field_test_target_id = entity_test_mul_property_data_entity_test__field_test.id AND entity_test__field_test.field_test_target_type = 'entity_test_mul'
LIMIT 10 OFFSET 0
The why around this would be if we'd add WHERE clause in the query instead of extra join condition something like this.
SELECT entity_test.id AS id, entity_test_entity_test__field_test.id AS entity_test_entity_test__field_test_id, entity_test_mul_property_data_entity_test__field_test.id AS entity_test_mul_property_data_entity_test__field_test_id
FROM
`entity_test` entity_test
LEFT JOIN `entity_test__field_test` entity_test__field_test ON entity_test.id = entity_test__field_test.entity_id AND entity_test__field_test.deleted = '0'
INNER JOIN `entity_test` entity_test_entity_test__field_test ON entity_test__field_test.field_test_target_id = entity_test_entity_test__field_test.id
INNER JOIN `entity_test_mul_property_data` entity_test_mul_property_data_entity_test__field_test ON entity_test__field_test.field_test_target_id = entity_test_mul_property_data_entity_test__field_test.id
WHERE entity_test__field_test.field_test_target_type IN ('entity_test', 'entity_test_mul')
LIMIT 10 OFFSET 0
The problem with this approach is it produced duplicate results just like when we add a relationship with term and term parent in node view. This can be avoided using distinct. Producing duplicates is fine IMO to avoid it user can always turn distinct on. If we'd go by this solution we'd have to implement a views relationship plugin which will add this where clause.
Do we've any other way around that?
Meanwhile I updated the tests. Currently it only asserts views data. Just have to create some views like EntityReferenceRelationshipTest and check the relationships but we have to finalize the approach first.
Oh I just made relationships required. You are right that's the reason I'm not getting results.
Though making those relationships not required gives me this error. Let me debug some more. Thanks for the replay.
This is finally complete now with tests for all the cases.
1. A DER field can create relationships with multiple entity types.
2. A DER field can create mutliple reverse relationships with multiple entity types.
In tests I only added one test per display to keep things simple.
Did you ever tried to place a DER field as part of basefields?
+++ b/dynamic_entity_reference.views.inc
@@ -0,0 +1,100 @@
+ // Entity reference field only has one target type whereas dynamic
+ // entity reference field can have multiple target types that is why we
+ // need extra join condition on target types.
Is there a reason why you don't typehint \Drupal\Core\Entity\Sql\TableMappingInterface. Is there something specific to the core implementation in your hook_views_data (I guess this is something coming from views itself?)
We should add dedicate tests with entity_test_der in which der is a basefield and whatever problem we'll find there we'll fix it follow up. I think for basic views implementation we should not block this issue on this point.
Anything to fix here?
getDedicatedDataTableName is not defined on the interface $table_mapping->getDedicatedDataTableName($field_storage),
I really like the idea. I'll create a follow up for this.
Thanks @dawehner for the reviews.
Thanks @damiankloip for discussing the issue with me at DrupalCon Amsterdam.
Thanks @larowlan for the manual testing.
Comments
Comment #2
jibranWith test fix.
Comment #3
jibranComment #7
jibranWell this passes locally.
Comment #10
jibranComment #30
jibranKeeping up with the core.
Comment #32
jibranJust debugging.
Comment #33
jibranComment #34
jibranComment #39
jibranIt is broken again :/
Comment #41
jibranMinor fixes
Comment #43
jibranThis is blocked on #2366093: Unable to set field value programmatically.
Comment #44
jibranReroll after #2366093: Unable to set field value programmatically.. This is blocked on #2372745: KernelTestBase ignores extensions in site-specific directories now.
Comment #45
jibranAlso blocked on #2378729: JoinPluginBase doesn't allow extra conditions on left table
Comment #46
jibranComment #48
jibranReroll and fixes. Core patch is dependent on join issue.
Comment #49
jibranAll the blockers are fixed now. Let's fix this issue as well.
Comment #50
larowlanI can't see anything wrong with this, but views isn't really my area of expertise.
Is it worth pinging someone else on VDC to give this a once-over?
If not, RTBC+1
Comment #53
jibranTest fix.
Comment #54
jibranAdded some docs as per @dawehner suggestions.
Comment #55
larowlanthanks for all the effort on this
Comment #56
socketwench commentedAre all the tests disappearing after applying the patch for anyone else or am I PEBKACing?
Comment #57
jibranFixes after #2451679: Validate cache contexts (+ cache contexts in some views plugins wrong). I'll commit it once the HEAD is back green.
@socketwench everything is working fine for me.
Comment #60
jibranI think we have a similar problem here #2451789: Entity reference joins to the wrong base table in views..
Comment #61
jibranFixes after #2451789: Entity reference joins to the wrong base table in views.. Need to rewrite
DynamicEntityReferenceRelationshipTestjust likeEntityReferenceRelationshipTestComment #63
jibranCopy paste fix.
Comment #64
jibranOk we have an issue now. I have been adding and extra condition to join which checks target type of current relationship. It works fine for single relationship but for multiple relationships join produce no result because a single value can't have two values of target types as can be seen in the resultant query.
The why around this would be if we'd add WHERE clause in the query instead of extra join condition something like this.
The problem with this approach is it produced duplicate results just like when we add a relationship with term and term parent in node view. This can be avoided using distinct. Producing duplicates is fine IMO to avoid it user can always turn distinct on. If we'd go by this solution we'd have to implement a views relationship plugin which will add this where clause.
Do we've any other way around that?
Meanwhile I updated the tests. Currently it only asserts views data. Just have to create some views like
EntityReferenceRelationshipTestand check the relationships but we have to finalize the approach first.Comment #66
dawehnerI'm curious why you use INNER JOIN by default? Isn't that the reason why you don't get any result?
Comment #67
jibranOh I just made relationships required. You are right that's the reason I'm not getting results.
Though making those relationships not required gives me this error. Let me debug some more. Thanks for the replay.
Comment #68
dpiComment #69
jibranI didn't debug the above error but thanks to @olli it is blocked on #2534780: Fatal error rendering fields using an optional relationship.
Comment #70
jibranThis is finally complete now with tests for all the cases.
1. A DER field can create relationships with multiple entity types.
2. A DER field can create mutliple reverse relationships with multiple entity types.
In tests I only added one test per display to keep things simple.
Comment #71
dawehnerI think this looks really great in general!
Did you ever tried to place a DER field as part of basefields?
Its just like old d7 field tables ...
Is there a reason why you don't typehint
\Drupal\Core\Entity\Sql\TableMappingInterface. Is there something specific to the core implementation in your hook_views_data (I guess this is something coming from views itself?)+1 for doing it right
Comment #72
jibranThanks for the review @dawehner
getDedicatedDataTableNameis not defined on the interface$table_mapping->getDedicatedDataTableName($field_storage),Comment #73
jibranCreated follow up issues.
Comment #75
jibranCommitted and pushed to 8.x-1.x.
Thanks @dawehner for the reviews.
Thanks @damiankloip for discussing the issue with me at DrupalCon Amsterdam.
Thanks @larowlan for the manual testing.