@@ -44,13 +44,17 @@ final class EagerLoadingExtension implements QueryCollectionExtensionInterface,
44
44
private $ serializerContextBuilder ;
45
45
private $ requestStack ;
46
46
47
- public function __construct (PropertyNameCollectionFactoryInterface $ propertyNameCollectionFactory , PropertyMetadataFactoryInterface $ propertyMetadataFactory , ResourceMetadataFactoryInterface $ resourceMetadataFactory , int $ maxJoins = 30 , bool $ forceEager = true , RequestStack $ requestStack = null , SerializerContextBuilderInterface $ serializerContextBuilder = null )
47
+ /**
48
+ * @TODO move $fetchPartial after $forceEager (@soyuka) in 3.0
49
+ */
50
+ public function __construct (PropertyNameCollectionFactoryInterface $ propertyNameCollectionFactory , PropertyMetadataFactoryInterface $ propertyMetadataFactory , ResourceMetadataFactoryInterface $ resourceMetadataFactory , int $ maxJoins = 30 , bool $ forceEager = true , RequestStack $ requestStack = null , SerializerContextBuilderInterface $ serializerContextBuilder = null , bool $ fetchPartial = false )
48
51
{
49
52
$ this ->propertyNameCollectionFactory = $ propertyNameCollectionFactory ;
50
53
$ this ->propertyMetadataFactory = $ propertyMetadataFactory ;
51
54
$ this ->resourceMetadataFactory = $ resourceMetadataFactory ;
52
55
$ this ->maxJoins = $ maxJoins ;
53
56
$ this ->forceEager = $ forceEager ;
57
+ $ this ->fetchPartial = $ fetchPartial ;
54
58
$ this ->serializerContextBuilder = $ serializerContextBuilder ;
55
59
$ this ->requestStack = $ requestStack ;
56
60
}
@@ -67,10 +71,11 @@ public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGenerator
67
71
}
68
72
69
73
$ forceEager = $ this ->shouldOperationForceEager ($ resourceClass , $ options );
74
+ $ fetchPartial = $ this ->shouldOperationFetchPartial ($ resourceClass , $ options );
70
75
71
76
$ groups = $ this ->getSerializerGroups ($ resourceClass , $ options , 'normalization_context ' );
72
77
73
- $ this ->joinRelations ($ queryBuilder , $ queryNameGenerator , $ resourceClass , $ forceEager , $ queryBuilder ->getRootAliases ()[0 ], $ groups );
78
+ $ this ->joinRelations ($ queryBuilder , $ queryNameGenerator , $ resourceClass , $ forceEager , $ fetchPartial , $ queryBuilder ->getRootAliases ()[0 ], $ groups );
74
79
}
75
80
76
81
/**
@@ -86,6 +91,7 @@ public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterf
86
91
}
87
92
88
93
$ forceEager = $ this ->shouldOperationForceEager ($ resourceClass , $ options );
94
+ $ fetchPartial = $ this ->shouldOperationFetchPartial ($ resourceClass , $ options );
89
95
90
96
if (isset ($ context ['groups ' ])) {
91
97
$ groups = ['serializer_groups ' => $ context ['groups ' ]];
@@ -95,7 +101,7 @@ public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterf
95
101
$ groups = $ this ->getSerializerGroups ($ resourceClass , $ options , 'normalization_context ' );
96
102
}
97
103
98
- $ this ->joinRelations ($ queryBuilder , $ queryNameGenerator , $ resourceClass , $ forceEager , $ queryBuilder ->getRootAliases ()[0 ], $ groups );
104
+ $ this ->joinRelations ($ queryBuilder , $ queryNameGenerator , $ resourceClass , $ forceEager , $ fetchPartial , $ queryBuilder ->getRootAliases ()[0 ], $ groups );
99
105
}
100
106
101
107
/**
@@ -112,7 +118,7 @@ public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterf
112
118
*
113
119
* @throws RuntimeException when the max number of joins has been reached
114
120
*/
115
- private function joinRelations (QueryBuilder $ queryBuilder , QueryNameGeneratorInterface $ queryNameGenerator , string $ resourceClass , bool $ forceEager , string $ parentAlias , array $ propertyMetadataOptions = [], bool $ wasLeftJoin = false , int &$ joinCount = 0 )
121
+ private function joinRelations (QueryBuilder $ queryBuilder , QueryNameGeneratorInterface $ queryNameGenerator , string $ resourceClass , bool $ forceEager , bool $ fetchPartial , string $ parentAlias , array $ propertyMetadataOptions = [], bool $ wasLeftJoin = false , int &$ joinCount = 0 )
116
122
{
117
123
if ($ joinCount > $ this ->maxJoins ) {
118
124
throw new RuntimeException ('The total number of joined relations has exceeded the specified maximum. Raise the limit if necessary. ' );
@@ -152,18 +158,23 @@ private function joinRelations(QueryBuilder $queryBuilder, QueryNameGeneratorInt
152
158
$ queryBuilder ->{$ method }(sprintf ('%s.%s ' , $ parentAlias , $ association ), $ associationAlias );
153
159
++$ joinCount ;
154
160
155
- try {
156
- $ this ->addSelect ($ queryBuilder , $ mapping ['targetEntity ' ], $ associationAlias , $ propertyMetadataOptions );
157
- } catch (ResourceClassNotFoundException $ resourceClassNotFoundException ) {
158
- continue ;
161
+ if (true === $ fetchPartial ) {
162
+ try {
163
+ $ this ->addSelect ($ queryBuilder , $ mapping ['targetEntity ' ], $ associationAlias , $ propertyMetadataOptions );
164
+ } catch (ResourceClassNotFoundException $ resourceClassNotFoundException ) {
165
+ continue ;
166
+ }
167
+ } else {
168
+ $ queryBuilder ->addSelect ($ associationAlias );
159
169
}
160
170
171
+ // Avoid recursion
161
172
if ($ mapping ['targetEntity ' ] === $ resourceClass ) {
162
173
$ queryBuilder ->addSelect ($ associationAlias );
163
174
continue ;
164
175
}
165
176
166
- $ this ->joinRelations ($ queryBuilder , $ queryNameGenerator , $ mapping ['targetEntity ' ], $ forceEager , $ associationAlias , $ propertyMetadataOptions , $ method === 'leftJoin ' , $ joinCount );
177
+ $ this ->joinRelations ($ queryBuilder , $ queryNameGenerator , $ mapping ['targetEntity ' ], $ forceEager , $ fetchPartial , $ associationAlias , $ propertyMetadataOptions , $ method === 'leftJoin ' , $ joinCount );
167
178
}
168
179
}
169
180
@@ -184,7 +195,7 @@ private function addSelect(QueryBuilder $queryBuilder, string $entity, string $a
184
195
}
185
196
186
197
//the field test allows to add methods to a Resource which do not reflect real database fields
187
- if (true === $ targetClassMetadata ->hasField ($ property ) && true === $ propertyMetadata ->isReadable ()) {
198
+ if (true === $ targetClassMetadata ->hasField ($ property ) && ( true === $ propertyMetadata ->getAttribute ( ' fetchable ' ) || true === $ propertyMetadata -> isReadable () )) {
188
199
$ select [] = $ property ;
189
200
}
190
201
}
0 commit comments