16
16
use ApiPlatform \Core \Exception \ResourceClassNotFoundException ;
17
17
use ApiPlatform \Core \Exception \RuntimeException ;
18
18
use ApiPlatform \Core \Metadata \Property \Factory \PropertyMetadataFactoryInterface ;
19
+ use ApiPlatform \Core \Metadata \Property \Factory \PropertyNameCollectionFactoryInterface ;
19
20
use ApiPlatform \Core \Metadata \Resource \Factory \ResourceMetadataFactoryInterface ;
20
21
use Doctrine \ORM \Mapping \ClassMetadataInfo ;
21
22
use Doctrine \ORM \QueryBuilder ;
@@ -35,8 +36,9 @@ final class EagerLoadingExtension implements QueryCollectionExtensionInterface,
35
36
private $ maxJoins ;
36
37
private $ forceEager ;
37
38
38
- public function __construct (PropertyMetadataFactoryInterface $ propertyMetadataFactory , ResourceMetadataFactoryInterface $ resourceMetadataFactory , int $ maxJoins = 30 , bool $ forceEager = true )
39
+ public function __construct (PropertyNameCollectionFactoryInterface $ propertyNameCollectionFactory , PropertyMetadataFactoryInterface $ propertyMetadataFactory , ResourceMetadataFactoryInterface $ resourceMetadataFactory , int $ maxJoins = 30 , bool $ forceEager = true )
39
40
{
41
+ $ this ->propertyNameCollectionFactory = $ propertyNameCollectionFactory ;
40
42
$ this ->propertyMetadataFactory = $ propertyMetadataFactory ;
41
43
$ this ->resourceMetadataFactory = $ resourceMetadataFactory ;
42
44
$ this ->maxJoins = $ maxJoins ;
@@ -132,8 +134,8 @@ private function joinRelations(QueryBuilder $queryBuilder, QueryNameGeneratorInt
132
134
continue ;
133
135
}
134
136
135
- $ joinColumns = $ mapping ['joinColumns ' ] ?? $ mapping [ ' joinTable ' ]['joinColumns ' ] ?? null ;
136
- if (false !== $ wasLeftJoin || ! isset ( $ joinColumns [ 0 ][ ' nullable ' ]) || false !== $ joinColumns [ 0 ][ ' nullable ' ] ) {
137
+ $ isNullable = $ mapping ['joinColumns ' ][ 0 ]['nullable ' ] ?? true ;
138
+ if (false !== $ wasLeftJoin || true === $ isNullable ) {
137
139
$ method = 'leftJoin ' ;
138
140
} else {
139
141
$ method = 'innerJoin ' ;
@@ -143,10 +145,39 @@ private function joinRelations(QueryBuilder $queryBuilder, QueryNameGeneratorInt
143
145
$ queryBuilder ->{$ method }(sprintf ('%s.%s ' , $ parentAlias , $ association ), $ associationAlias );
144
146
++$ joinCount ;
145
147
148
+ try {
149
+ $ this ->addSelect ($ queryBuilder , $ mapping ['targetEntity ' ], $ associationAlias , $ propertyMetadataOptions );
150
+ } catch (ResourceClassNotFoundException $ resourceClassNotFoundException ) {
151
+ continue ;
152
+ }
153
+
146
154
$ this ->joinRelations ($ queryBuilder , $ queryNameGenerator , $ mapping ['targetEntity ' ], $ forceEager , $ associationAlias , $ propertyMetadataOptions , $ method === 'leftJoin ' , $ joinCount );
147
155
}
148
156
}
149
157
158
+ private function addSelect (QueryBuilder $ queryBuilder , string $ entity , string $ associationAlias , array $ propertyMetadataOptions )
159
+ {
160
+ $ select = [];
161
+ $ entityManager = $ queryBuilder ->getEntityManager ();
162
+ $ targetClassMetadata = $ entityManager ->getClassMetadata ($ entity );
163
+
164
+ foreach ($ this ->propertyNameCollectionFactory ->create ($ entity ) as $ property ) {
165
+ $ propertyMetadata = $ this ->propertyMetadataFactory ->create ($ entity , $ property , $ propertyMetadataOptions );
166
+
167
+ if (true === $ propertyMetadata ->isIdentifier ()) {
168
+ $ select [] = $ property ;
169
+ continue ;
170
+ }
171
+
172
+ //the field test allows to add methods to a Resource which do not reflect real database fields
173
+ if (true === $ targetClassMetadata ->hasField ($ property ) && true === $ propertyMetadata ->isReadable ()) {
174
+ $ select [] = $ property ;
175
+ }
176
+ }
177
+
178
+ $ queryBuilder ->addSelect (sprintf ('partial %s.{%s} ' , $ associationAlias , implode (', ' , $ select )));
179
+ }
180
+
150
181
/**
151
182
* Gets serializer groups if available, if not it returns the $options array.
152
183
*
0 commit comments