1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace Doctrine\Tests\ORM\Hydration; |
6
|
|
|
|
7
|
|
|
use Doctrine\DBAL\Types\Type; |
8
|
|
|
use Doctrine\ORM\Internal\Hydration\ObjectHydrator; |
9
|
|
|
use Doctrine\ORM\Mapping\FetchMode; |
10
|
|
|
use Doctrine\ORM\PersistentCollection; |
11
|
|
|
use Doctrine\ORM\Proxy\Factory\ProxyFactory; |
12
|
|
|
use Doctrine\ORM\Query; |
13
|
|
|
use Doctrine\ORM\Query\ResultSetMapping; |
14
|
|
|
use Doctrine\Tests\Mocks\HydratorMockStatement; |
15
|
|
|
use Doctrine\Tests\Models\CMS\CmsAddress; |
16
|
|
|
use Doctrine\Tests\Models\CMS\CmsArticle; |
17
|
|
|
use Doctrine\Tests\Models\CMS\CmsComment; |
18
|
|
|
use Doctrine\Tests\Models\CMS\CmsGroup; |
19
|
|
|
use Doctrine\Tests\Models\CMS\CmsPhonenumber; |
20
|
|
|
use Doctrine\Tests\Models\CMS\CmsUser; |
21
|
|
|
use Doctrine\Tests\Models\Company\CompanyEmployee; |
22
|
|
|
use Doctrine\Tests\Models\Company\CompanyFixContract; |
23
|
|
|
use Doctrine\Tests\Models\Company\CompanyPerson; |
24
|
|
|
use Doctrine\Tests\Models\ECommerce\ECommerceProduct; |
25
|
|
|
use Doctrine\Tests\Models\ECommerce\ECommerceShipping; |
26
|
|
|
use Doctrine\Tests\Models\Forum\ForumBoard; |
27
|
|
|
use Doctrine\Tests\Models\Forum\ForumCategory; |
28
|
|
|
use Doctrine\Tests\Models\Hydration\EntityWithArrayDefaultArrayValueM2M; |
29
|
|
|
use Doctrine\Tests\Models\Hydration\SimpleEntity; |
30
|
|
|
use ProxyManager\Configuration; |
31
|
|
|
use ProxyManager\Factory\LazyLoadingGhostFactory; |
32
|
|
|
|
33
|
|
|
class ObjectHydratorTest extends HydrationTestCase |
34
|
|
|
{ |
35
|
|
|
public function provideDataForUserEntityResult() |
36
|
|
|
{ |
37
|
|
|
return [ |
38
|
|
|
[0], |
39
|
|
|
['user'], |
40
|
|
|
]; |
41
|
|
|
} |
42
|
|
|
|
43
|
|
|
public function provideDataForMultipleRootEntityResult() |
44
|
|
|
{ |
45
|
|
|
return [ |
46
|
|
|
[0, 0], |
47
|
|
|
['user', 0], |
48
|
|
|
[0, 'article'], |
49
|
|
|
['user', 'article'], |
50
|
|
|
]; |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
public function provideDataForProductEntityResult() |
54
|
|
|
{ |
55
|
|
|
return [ |
56
|
|
|
[0], |
57
|
|
|
['product'], |
58
|
|
|
]; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* SELECT PARTIAL u.{id,name} |
63
|
|
|
* FROM Doctrine\Tests\Models\CMS\CmsUser u |
64
|
|
|
*/ |
65
|
|
|
public function testSimpleEntityQuery() : void |
66
|
|
|
{ |
67
|
|
|
$rsm = new ResultSetMapping(); |
68
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u'); |
69
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
70
|
|
|
$rsm->addFieldResult('u', 'u__name', 'name'); |
71
|
|
|
|
72
|
|
|
// Faked result set |
73
|
|
|
$resultSet = [ |
74
|
|
|
[ |
75
|
|
|
'u__id' => '1', |
76
|
|
|
'u__name' => 'romanb', |
77
|
|
|
], |
78
|
|
|
[ |
79
|
|
|
'u__id' => '2', |
80
|
|
|
'u__name' => 'jwage', |
81
|
|
|
], |
82
|
|
|
]; |
83
|
|
|
|
84
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
85
|
|
|
$hydrator = new ObjectHydrator($this->em); |
86
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
87
|
|
|
|
88
|
|
|
self::assertCount(2, $result); |
89
|
|
|
|
90
|
|
|
self::assertInstanceOf(CmsUser::class, $result[0]); |
91
|
|
|
self::assertInstanceOf(CmsUser::class, $result[1]); |
92
|
|
|
|
93
|
|
|
self::assertEquals(1, $result[0]->id); |
94
|
|
|
self::assertEquals('romanb', $result[0]->name); |
95
|
|
|
|
96
|
|
|
self::assertEquals(2, $result[1]->id); |
97
|
|
|
self::assertEquals('jwage', $result[1]->name); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* SELECT PARTIAL u.{id,name} AS user |
102
|
|
|
* FROM Doctrine\Tests\Models\CMS\CmsUser u |
103
|
|
|
*/ |
104
|
|
|
public function testSimpleEntityQueryWithAliasedUserEntity() : void |
105
|
|
|
{ |
106
|
|
|
$rsm = new ResultSetMapping(); |
107
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u', 'user'); |
108
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
109
|
|
|
$rsm->addFieldResult('u', 'u__name', 'name'); |
110
|
|
|
|
111
|
|
|
// Faked result set |
112
|
|
|
$resultSet = [ |
113
|
|
|
[ |
114
|
|
|
'u__id' => '1', |
115
|
|
|
'u__name' => 'romanb', |
116
|
|
|
], |
117
|
|
|
[ |
118
|
|
|
'u__id' => '2', |
119
|
|
|
'u__name' => 'jwage', |
120
|
|
|
], |
121
|
|
|
]; |
122
|
|
|
|
123
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
124
|
|
|
$hydrator = new ObjectHydrator($this->em); |
125
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
126
|
|
|
|
127
|
|
|
self::assertCount(2, $result); |
128
|
|
|
|
129
|
|
|
self::assertArrayHasKey('user', $result[0]); |
130
|
|
|
self::assertInstanceOf(CmsUser::class, $result[0]['user']); |
131
|
|
|
|
132
|
|
|
self::assertArrayHasKey('user', $result[1]); |
133
|
|
|
self::assertInstanceOf(CmsUser::class, $result[1]['user']); |
134
|
|
|
|
135
|
|
|
self::assertEquals(1, $result[0]['user']->id); |
136
|
|
|
self::assertEquals('romanb', $result[0]['user']->name); |
137
|
|
|
|
138
|
|
|
self::assertEquals(2, $result[1]['user']->id); |
139
|
|
|
self::assertEquals('jwage', $result[1]['user']->name); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
/** |
143
|
|
|
* SELECT PARTIAL u.{id, name}, PARTIAL a.{id, topic} |
144
|
|
|
* FROM Doctrine\Tests\Models\CMS\CmsUser u, Doctrine\Tests\Models\CMS\CmsArticle a |
145
|
|
|
*/ |
146
|
|
|
public function testSimpleMultipleRootEntityQuery() : void |
147
|
|
|
{ |
148
|
|
|
$rsm = new ResultSetMapping(); |
149
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u'); |
150
|
|
|
$rsm->addEntityResult(CmsArticle::class, 'a'); |
151
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
152
|
|
|
$rsm->addFieldResult('u', 'u__name', 'name'); |
153
|
|
|
$rsm->addFieldResult('a', 'a__id', 'id'); |
154
|
|
|
$rsm->addFieldResult('a', 'a__topic', 'topic'); |
155
|
|
|
|
156
|
|
|
// Faked result set |
157
|
|
|
$resultSet = [ |
158
|
|
|
[ |
159
|
|
|
'u__id' => '1', |
160
|
|
|
'u__name' => 'romanb', |
161
|
|
|
'a__id' => '1', |
162
|
|
|
'a__topic' => 'Cool things.', |
163
|
|
|
], |
164
|
|
|
[ |
165
|
|
|
'u__id' => '2', |
166
|
|
|
'u__name' => 'jwage', |
167
|
|
|
'a__id' => '2', |
168
|
|
|
'a__topic' => 'Cool things II.', |
169
|
|
|
], |
170
|
|
|
]; |
171
|
|
|
|
172
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
173
|
|
|
$hydrator = new ObjectHydrator($this->em); |
174
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
175
|
|
|
|
176
|
|
|
self::assertCount(4, $result); |
177
|
|
|
|
178
|
|
|
self::assertInstanceOf(CmsUser::class, $result[0]); |
179
|
|
|
self::assertInstanceOf(CmsArticle::class, $result[1]); |
180
|
|
|
self::assertInstanceOf(CmsUser::class, $result[2]); |
181
|
|
|
self::assertInstanceOf(CmsArticle::class, $result[3]); |
182
|
|
|
|
183
|
|
|
self::assertEquals(1, $result[0]->id); |
184
|
|
|
self::assertEquals('romanb', $result[0]->name); |
185
|
|
|
|
186
|
|
|
self::assertEquals(1, $result[1]->id); |
187
|
|
|
self::assertEquals('Cool things.', $result[1]->topic); |
188
|
|
|
|
189
|
|
|
self::assertEquals(2, $result[2]->id); |
190
|
|
|
self::assertEquals('jwage', $result[2]->name); |
191
|
|
|
|
192
|
|
|
self::assertEquals(2, $result[3]->id); |
193
|
|
|
self::assertEquals('Cool things II.', $result[3]->topic); |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* SELECT PARTIAL u.{id, name} AS user, PARTIAL a.{id, topic} |
198
|
|
|
* FROM Doctrine\Tests\Models\CMS\CmsUser u, Doctrine\Tests\Models\CMS\CmsArticle a |
199
|
|
|
*/ |
200
|
|
|
public function testSimpleMultipleRootEntityQueryWithAliasedUserEntity() : void |
201
|
|
|
{ |
202
|
|
|
$rsm = new ResultSetMapping(); |
203
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u', 'user'); |
204
|
|
|
$rsm->addEntityResult(CmsArticle::class, 'a'); |
205
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
206
|
|
|
$rsm->addFieldResult('u', 'u__name', 'name'); |
207
|
|
|
$rsm->addFieldResult('a', 'a__id', 'id'); |
208
|
|
|
$rsm->addFieldResult('a', 'a__topic', 'topic'); |
209
|
|
|
|
210
|
|
|
// Faked result set |
211
|
|
|
$resultSet = [ |
212
|
|
|
[ |
213
|
|
|
'u__id' => '1', |
214
|
|
|
'u__name' => 'romanb', |
215
|
|
|
'a__id' => '1', |
216
|
|
|
'a__topic' => 'Cool things.', |
217
|
|
|
], |
218
|
|
|
[ |
219
|
|
|
'u__id' => '2', |
220
|
|
|
'u__name' => 'jwage', |
221
|
|
|
'a__id' => '2', |
222
|
|
|
'a__topic' => 'Cool things II.', |
223
|
|
|
], |
224
|
|
|
]; |
225
|
|
|
|
226
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
227
|
|
|
$hydrator = new ObjectHydrator($this->em); |
228
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
229
|
|
|
|
230
|
|
|
self::assertCount(4, $result); |
231
|
|
|
|
232
|
|
|
self::assertArrayHasKey('user', $result[0]); |
233
|
|
|
self::assertArrayNotHasKey(0, $result[0]); |
234
|
|
|
self::assertInstanceOf(CmsUser::class, $result[0]['user']); |
235
|
|
|
self::assertEquals(1, $result[0]['user']->id); |
236
|
|
|
self::assertEquals('romanb', $result[0]['user']->name); |
237
|
|
|
|
238
|
|
|
self::assertArrayHasKey(0, $result[1]); |
239
|
|
|
self::assertArrayNotHasKey('user', $result[1]); |
240
|
|
|
self::assertInstanceOf(CmsArticle::class, $result[1][0]); |
241
|
|
|
self::assertEquals(1, $result[1][0]->id); |
242
|
|
|
self::assertEquals('Cool things.', $result[1][0]->topic); |
243
|
|
|
|
244
|
|
|
self::assertArrayHasKey('user', $result[2]); |
245
|
|
|
self::assertArrayNotHasKey(0, $result[2]); |
246
|
|
|
self::assertInstanceOf(CmsUser::class, $result[2]['user']); |
247
|
|
|
self::assertEquals(2, $result[2]['user']->id); |
248
|
|
|
self::assertEquals('jwage', $result[2]['user']->name); |
249
|
|
|
|
250
|
|
|
self::assertArrayHasKey(0, $result[3]); |
251
|
|
|
self::assertArrayNotHasKey('user', $result[3]); |
252
|
|
|
self::assertInstanceOf(CmsArticle::class, $result[3][0]); |
253
|
|
|
self::assertEquals(2, $result[3][0]->id); |
254
|
|
|
self::assertEquals('Cool things II.', $result[3][0]->topic); |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
/** |
258
|
|
|
* SELECT PARTIAL u.{id, name}, PARTIAL a.{id, topic} AS article |
259
|
|
|
* FROM Doctrine\Tests\Models\CMS\CmsUser u, Doctrine\Tests\Models\CMS\CmsArticle a |
260
|
|
|
*/ |
261
|
|
|
public function testSimpleMultipleRootEntityQueryWithAliasedArticleEntity() : void |
262
|
|
|
{ |
263
|
|
|
$rsm = new ResultSetMapping(); |
264
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u'); |
265
|
|
|
$rsm->addEntityResult(CmsArticle::class, 'a', 'article'); |
266
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
267
|
|
|
$rsm->addFieldResult('u', 'u__name', 'name'); |
268
|
|
|
$rsm->addFieldResult('a', 'a__id', 'id'); |
269
|
|
|
$rsm->addFieldResult('a', 'a__topic', 'topic'); |
270
|
|
|
|
271
|
|
|
// Faked result set |
272
|
|
|
$resultSet = [ |
273
|
|
|
[ |
274
|
|
|
'u__id' => '1', |
275
|
|
|
'u__name' => 'romanb', |
276
|
|
|
'a__id' => '1', |
277
|
|
|
'a__topic' => 'Cool things.', |
278
|
|
|
], |
279
|
|
|
[ |
280
|
|
|
'u__id' => '2', |
281
|
|
|
'u__name' => 'jwage', |
282
|
|
|
'a__id' => '2', |
283
|
|
|
'a__topic' => 'Cool things II.', |
284
|
|
|
], |
285
|
|
|
]; |
286
|
|
|
|
287
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
288
|
|
|
$hydrator = new ObjectHydrator($this->em); |
289
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
290
|
|
|
|
291
|
|
|
self::assertCount(4, $result); |
292
|
|
|
|
293
|
|
|
self::assertArrayHasKey(0, $result[0]); |
294
|
|
|
self::assertArrayNotHasKey('article', $result[0]); |
295
|
|
|
self::assertInstanceOf(CmsUser::class, $result[0][0]); |
296
|
|
|
self::assertEquals(1, $result[0][0]->id); |
297
|
|
|
self::assertEquals('romanb', $result[0][0]->name); |
298
|
|
|
|
299
|
|
|
self::assertArrayHasKey('article', $result[1]); |
300
|
|
|
self::assertArrayNotHasKey(0, $result[1]); |
301
|
|
|
self::assertInstanceOf(CmsArticle::class, $result[1]['article']); |
302
|
|
|
self::assertEquals(1, $result[1]['article']->id); |
303
|
|
|
self::assertEquals('Cool things.', $result[1]['article']->topic); |
304
|
|
|
|
305
|
|
|
self::assertArrayHasKey(0, $result[2]); |
306
|
|
|
self::assertArrayNotHasKey('article', $result[2]); |
307
|
|
|
self::assertInstanceOf(CmsUser::class, $result[2][0]); |
308
|
|
|
self::assertEquals(2, $result[2][0]->id); |
309
|
|
|
self::assertEquals('jwage', $result[2][0]->name); |
310
|
|
|
|
311
|
|
|
self::assertArrayHasKey('article', $result[3]); |
312
|
|
|
self::assertArrayNotHasKey(0, $result[3]); |
313
|
|
|
self::assertInstanceOf(CmsArticle::class, $result[3]['article']); |
314
|
|
|
self::assertEquals(2, $result[3]['article']->id); |
315
|
|
|
self::assertEquals('Cool things II.', $result[3]['article']->topic); |
316
|
|
|
} |
317
|
|
|
|
318
|
|
|
/** |
319
|
|
|
* SELECT PARTIAL u.{id, name} AS user, PARTIAL a.{id, topic} AS article |
320
|
|
|
* FROM Doctrine\Tests\Models\CMS\CmsUser u, Doctrine\Tests\Models\CMS\CmsArticle a |
321
|
|
|
*/ |
322
|
|
|
public function testSimpleMultipleRootEntityQueryWithAliasedEntities() : void |
323
|
|
|
{ |
324
|
|
|
$rsm = new ResultSetMapping(); |
325
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u', 'user'); |
326
|
|
|
$rsm->addEntityResult(CmsArticle::class, 'a', 'article'); |
327
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
328
|
|
|
$rsm->addFieldResult('u', 'u__name', 'name'); |
329
|
|
|
$rsm->addFieldResult('a', 'a__id', 'id'); |
330
|
|
|
$rsm->addFieldResult('a', 'a__topic', 'topic'); |
331
|
|
|
|
332
|
|
|
// Faked result set |
333
|
|
|
$resultSet = [ |
334
|
|
|
[ |
335
|
|
|
'u__id' => '1', |
336
|
|
|
'u__name' => 'romanb', |
337
|
|
|
'a__id' => '1', |
338
|
|
|
'a__topic' => 'Cool things.', |
339
|
|
|
], |
340
|
|
|
[ |
341
|
|
|
'u__id' => '2', |
342
|
|
|
'u__name' => 'jwage', |
343
|
|
|
'a__id' => '2', |
344
|
|
|
'a__topic' => 'Cool things II.', |
345
|
|
|
], |
346
|
|
|
]; |
347
|
|
|
|
348
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
349
|
|
|
$hydrator = new ObjectHydrator($this->em); |
350
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
351
|
|
|
|
352
|
|
|
self::assertCount(4, $result); |
353
|
|
|
|
354
|
|
|
self::assertArrayHasKey('user', $result[0]); |
355
|
|
|
self::assertArrayNotHasKey('article', $result[0]); |
356
|
|
|
self::assertInstanceOf(CmsUser::class, $result[0]['user']); |
357
|
|
|
self::assertEquals(1, $result[0]['user']->id); |
358
|
|
|
self::assertEquals('romanb', $result[0]['user']->name); |
359
|
|
|
|
360
|
|
|
self::assertArrayHasKey('article', $result[1]); |
361
|
|
|
self::assertArrayNotHasKey('user', $result[1]); |
362
|
|
|
self::assertInstanceOf(CmsArticle::class, $result[1]['article']); |
363
|
|
|
self::assertEquals(1, $result[1]['article']->id); |
364
|
|
|
self::assertEquals('Cool things.', $result[1]['article']->topic); |
365
|
|
|
|
366
|
|
|
self::assertArrayHasKey('user', $result[2]); |
367
|
|
|
self::assertArrayNotHasKey('article', $result[2]); |
368
|
|
|
self::assertInstanceOf(CmsUser::class, $result[2]['user']); |
369
|
|
|
self::assertEquals(2, $result[2]['user']->id); |
370
|
|
|
self::assertEquals('jwage', $result[2]['user']->name); |
371
|
|
|
|
372
|
|
|
self::assertArrayHasKey('article', $result[3]); |
373
|
|
|
self::assertArrayNotHasKey('user', $result[3]); |
374
|
|
|
self::assertInstanceOf(CmsArticle::class, $result[3]['article']); |
375
|
|
|
self::assertEquals(2, $result[3]['article']->id); |
376
|
|
|
self::assertEquals('Cool things II.', $result[3]['article']->topic); |
377
|
|
|
} |
378
|
|
|
|
379
|
|
|
/** |
380
|
|
|
* SELECT PARTIAL u.{id, status}, COUNT(p.phonenumber) numPhones |
381
|
|
|
* FROM User u |
382
|
|
|
* JOIN u.phonenumbers p |
383
|
|
|
* GROUP BY u.id |
384
|
|
|
* |
385
|
|
|
* @dataProvider provideDataForUserEntityResult |
386
|
|
|
*/ |
387
|
|
|
public function testMixedQueryNormalJoin($userEntityKey) : void |
388
|
|
|
{ |
389
|
|
|
$rsm = new ResultSetMapping(); |
390
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u', $userEntityKey ?: null); |
391
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
392
|
|
|
$rsm->addFieldResult('u', 'u__status', 'status'); |
393
|
|
|
$rsm->addScalarResult('sclr0', 'numPhones', Type::getType('integer')); |
394
|
|
|
|
395
|
|
|
// Faked result set |
396
|
|
|
$resultSet = [ |
397
|
|
|
//row1 |
398
|
|
|
[ |
399
|
|
|
'u__id' => '1', |
400
|
|
|
'u__status' => 'developer', |
401
|
|
|
'sclr0' => '2', |
402
|
|
|
], |
403
|
|
|
[ |
404
|
|
|
'u__id' => '2', |
405
|
|
|
'u__status' => 'developer', |
406
|
|
|
'sclr0' => '1', |
407
|
|
|
], |
408
|
|
|
]; |
409
|
|
|
|
410
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
411
|
|
|
$hydrator = new ObjectHydrator($this->em); |
412
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
413
|
|
|
|
414
|
|
|
self::assertCount(2, $result); |
415
|
|
|
|
416
|
|
|
self::assertInternalType('array', $result); |
|
|
|
|
417
|
|
|
self::assertInternalType('array', $result[0]); |
|
|
|
|
418
|
|
|
self::assertInternalType('array', $result[1]); |
|
|
|
|
419
|
|
|
|
420
|
|
|
// first user => 2 phonenumbers |
421
|
|
|
self::assertEquals(2, $result[0]['numPhones']); |
422
|
|
|
self::assertInstanceOf(CmsUser::class, $result[0][$userEntityKey]); |
423
|
|
|
|
424
|
|
|
// second user => 1 phonenumber |
425
|
|
|
self::assertEquals(1, $result[1]['numPhones']); |
426
|
|
|
self::assertInstanceOf(CmsUser::class, $result[1][$userEntityKey]); |
427
|
|
|
} |
428
|
|
|
|
429
|
|
|
/** |
430
|
|
|
* SELECT PARTIAL u.{id, status}, PARTIAL p.{phonenumber}, UPPER(u.name) nameUpper |
431
|
|
|
* FROM Doctrine\Tests\Models\CMS\CmsUser u |
432
|
|
|
* JOIN u.phonenumbers p |
433
|
|
|
* |
434
|
|
|
* @dataProvider provideDataForUserEntityResult |
435
|
|
|
*/ |
436
|
|
|
public function testMixedQueryFetchJoin($userEntityKey) : void |
437
|
|
|
{ |
438
|
|
|
$rsm = new ResultSetMapping(); |
439
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u', $userEntityKey ?: null); |
440
|
|
|
$rsm->addJoinedEntityResult( |
441
|
|
|
CmsPhonenumber::class, |
442
|
|
|
'p', |
443
|
|
|
'u', |
444
|
|
|
'phonenumbers' |
445
|
|
|
); |
446
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
447
|
|
|
$rsm->addFieldResult('u', 'u__status', 'status'); |
448
|
|
|
$rsm->addFieldResult('p', 'p__phonenumber', 'phonenumber'); |
449
|
|
|
$rsm->addScalarResult('sclr0', 'nameUpper', Type::getType('string')); |
450
|
|
|
|
451
|
|
|
// Faked result set |
452
|
|
|
$resultSet = [ |
453
|
|
|
//row1 |
454
|
|
|
[ |
455
|
|
|
'u__id' => '1', |
456
|
|
|
'u__status' => 'developer', |
457
|
|
|
'p__phonenumber' => '42', |
458
|
|
|
'sclr0' => 'ROMANB', |
459
|
|
|
], |
460
|
|
|
[ |
461
|
|
|
'u__id' => '1', |
462
|
|
|
'u__status' => 'developer', |
463
|
|
|
'p__phonenumber' => '43', |
464
|
|
|
'sclr0' => 'ROMANB', |
465
|
|
|
], |
466
|
|
|
[ |
467
|
|
|
'u__id' => '2', |
468
|
|
|
'u__status' => 'developer', |
469
|
|
|
'p__phonenumber' => '91', |
470
|
|
|
'sclr0' => 'JWAGE', |
471
|
|
|
], |
472
|
|
|
]; |
473
|
|
|
|
474
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
475
|
|
|
$hydrator = new ObjectHydrator($this->em); |
476
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
477
|
|
|
|
478
|
|
|
self::assertCount(2, $result); |
479
|
|
|
|
480
|
|
|
self::assertInternalType('array', $result); |
|
|
|
|
481
|
|
|
self::assertInternalType('array', $result[0]); |
|
|
|
|
482
|
|
|
self::assertInternalType('array', $result[1]); |
|
|
|
|
483
|
|
|
|
484
|
|
|
self::assertInstanceOf(CmsUser::class, $result[0][$userEntityKey]); |
485
|
|
|
self::assertInstanceOf(PersistentCollection::class, $result[0][$userEntityKey]->phonenumbers); |
486
|
|
|
self::assertInstanceOf(CmsPhonenumber::class, $result[0][$userEntityKey]->phonenumbers[0]); |
487
|
|
|
|
488
|
|
|
self::assertInstanceOf(CmsUser::class, $result[1][$userEntityKey]); |
489
|
|
|
self::assertInstanceOf(PersistentCollection::class, $result[1][$userEntityKey]->phonenumbers); |
490
|
|
|
self::assertInstanceOf(CmsPhonenumber::class, $result[0][$userEntityKey]->phonenumbers[1]); |
491
|
|
|
|
492
|
|
|
// first user => 2 phonenumbers |
493
|
|
|
self::assertCount(2, $result[0][$userEntityKey]->phonenumbers); |
494
|
|
|
self::assertEquals('ROMANB', $result[0]['nameUpper']); |
495
|
|
|
|
496
|
|
|
// second user => 1 phonenumber |
497
|
|
|
self::assertCount(1, $result[1][$userEntityKey]->phonenumbers); |
498
|
|
|
self::assertEquals('JWAGE', $result[1]['nameUpper']); |
499
|
|
|
|
500
|
|
|
self::assertEquals(42, $result[0][$userEntityKey]->phonenumbers[0]->phonenumber); |
501
|
|
|
self::assertEquals(43, $result[0][$userEntityKey]->phonenumbers[1]->phonenumber); |
502
|
|
|
self::assertEquals(91, $result[1][$userEntityKey]->phonenumbers[0]->phonenumber); |
503
|
|
|
} |
504
|
|
|
|
505
|
|
|
/** |
506
|
|
|
* SELECT u, p, UPPER(u.name) nameUpper |
507
|
|
|
* FROM User u |
508
|
|
|
* INDEX BY u.id |
509
|
|
|
* JOIN u.phonenumbers p |
510
|
|
|
* INDEX BY p.phonenumber |
511
|
|
|
* |
512
|
|
|
* @dataProvider provideDataForUserEntityResult |
513
|
|
|
*/ |
514
|
|
|
public function testMixedQueryFetchJoinCustomIndex($userEntityKey) : void |
515
|
|
|
{ |
516
|
|
|
$rsm = new ResultSetMapping(); |
517
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u', $userEntityKey ?: null); |
518
|
|
|
$rsm->addJoinedEntityResult( |
519
|
|
|
CmsPhonenumber::class, |
520
|
|
|
'p', |
521
|
|
|
'u', |
522
|
|
|
'phonenumbers' |
523
|
|
|
); |
524
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
525
|
|
|
$rsm->addFieldResult('u', 'u__status', 'status'); |
526
|
|
|
$rsm->addScalarResult('sclr0', 'nameUpper', Type::getType('string')); |
527
|
|
|
$rsm->addFieldResult('p', 'p__phonenumber', 'phonenumber'); |
528
|
|
|
$rsm->addIndexBy('u', 'id'); |
529
|
|
|
$rsm->addIndexBy('p', 'phonenumber'); |
530
|
|
|
|
531
|
|
|
// Faked result set |
532
|
|
|
$resultSet = [ |
533
|
|
|
//row1 |
534
|
|
|
[ |
535
|
|
|
'u__id' => '1', |
536
|
|
|
'u__status' => 'developer', |
537
|
|
|
'sclr0' => 'ROMANB', |
538
|
|
|
'p__phonenumber' => '42', |
539
|
|
|
], |
540
|
|
|
[ |
541
|
|
|
'u__id' => '1', |
542
|
|
|
'u__status' => 'developer', |
543
|
|
|
'sclr0' => 'ROMANB', |
544
|
|
|
'p__phonenumber' => '43', |
545
|
|
|
], |
546
|
|
|
[ |
547
|
|
|
'u__id' => '2', |
548
|
|
|
'u__status' => 'developer', |
549
|
|
|
'sclr0' => 'JWAGE', |
550
|
|
|
'p__phonenumber' => '91', |
551
|
|
|
], |
552
|
|
|
]; |
553
|
|
|
|
554
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
555
|
|
|
$hydrator = new ObjectHydrator($this->em); |
556
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
557
|
|
|
|
558
|
|
|
self::assertCount(2, $result); |
559
|
|
|
|
560
|
|
|
self::assertInternalType('array', $result); |
|
|
|
|
561
|
|
|
self::assertInternalType('array', $result[1]); |
|
|
|
|
562
|
|
|
self::assertInternalType('array', $result[2]); |
|
|
|
|
563
|
|
|
|
564
|
|
|
// test the scalar values |
565
|
|
|
self::assertEquals('ROMANB', $result[1]['nameUpper']); |
566
|
|
|
self::assertEquals('JWAGE', $result[2]['nameUpper']); |
567
|
|
|
|
568
|
|
|
self::assertInstanceOf(CmsUser::class, $result[1][$userEntityKey]); |
569
|
|
|
self::assertInstanceOf(CmsUser::class, $result[2][$userEntityKey]); |
570
|
|
|
self::assertInstanceOf(PersistentCollection::class, $result[1][$userEntityKey]->phonenumbers); |
571
|
|
|
|
572
|
|
|
// first user => 2 phonenumbers. notice the custom indexing by user id |
573
|
|
|
self::assertCount(2, $result[1][$userEntityKey]->phonenumbers); |
574
|
|
|
|
575
|
|
|
// second user => 1 phonenumber. notice the custom indexing by user id |
576
|
|
|
self::assertCount(1, $result[2][$userEntityKey]->phonenumbers); |
577
|
|
|
|
578
|
|
|
// test the custom indexing of the phonenumbers |
579
|
|
|
self::assertTrue(isset($result[1][$userEntityKey]->phonenumbers['42'])); |
580
|
|
|
self::assertTrue(isset($result[1][$userEntityKey]->phonenumbers['43'])); |
581
|
|
|
self::assertTrue(isset($result[2][$userEntityKey]->phonenumbers['91'])); |
582
|
|
|
} |
583
|
|
|
|
584
|
|
|
/** |
585
|
|
|
* SELECT u, p, UPPER(u.name) nameUpper, a |
586
|
|
|
* FROM User u |
587
|
|
|
* JOIN u.phonenumbers p |
588
|
|
|
* JOIN u.articles a |
589
|
|
|
* |
590
|
|
|
* @dataProvider provideDataForUserEntityResult |
591
|
|
|
*/ |
592
|
|
|
public function testMixedQueryMultipleFetchJoin($userEntityKey) : void |
593
|
|
|
{ |
594
|
|
|
$rsm = new ResultSetMapping(); |
595
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u', $userEntityKey ?: null); |
596
|
|
|
$rsm->addJoinedEntityResult( |
597
|
|
|
CmsPhonenumber::class, |
598
|
|
|
'p', |
599
|
|
|
'u', |
600
|
|
|
'phonenumbers' |
601
|
|
|
); |
602
|
|
|
$rsm->addJoinedEntityResult( |
603
|
|
|
CmsArticle::class, |
604
|
|
|
'a', |
605
|
|
|
'u', |
606
|
|
|
'articles' |
607
|
|
|
); |
608
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
609
|
|
|
$rsm->addFieldResult('u', 'u__status', 'status'); |
610
|
|
|
$rsm->addScalarResult('sclr0', 'nameUpper', Type::getType('string')); |
611
|
|
|
$rsm->addFieldResult('p', 'p__phonenumber', 'phonenumber'); |
612
|
|
|
$rsm->addFieldResult('a', 'a__id', 'id'); |
613
|
|
|
$rsm->addFieldResult('a', 'a__topic', 'topic'); |
614
|
|
|
|
615
|
|
|
// Faked result set |
616
|
|
|
$resultSet = [ |
617
|
|
|
//row1 |
618
|
|
|
[ |
619
|
|
|
'u__id' => '1', |
620
|
|
|
'u__status' => 'developer', |
621
|
|
|
'sclr0' => 'ROMANB', |
622
|
|
|
'p__phonenumber' => '42', |
623
|
|
|
'a__id' => '1', |
624
|
|
|
'a__topic' => 'Getting things done!', |
625
|
|
|
], |
626
|
|
|
[ |
627
|
|
|
'u__id' => '1', |
628
|
|
|
'u__status' => 'developer', |
629
|
|
|
'sclr0' => 'ROMANB', |
630
|
|
|
'p__phonenumber' => '43', |
631
|
|
|
'a__id' => '1', |
632
|
|
|
'a__topic' => 'Getting things done!', |
633
|
|
|
], |
634
|
|
|
[ |
635
|
|
|
'u__id' => '1', |
636
|
|
|
'u__status' => 'developer', |
637
|
|
|
'sclr0' => 'ROMANB', |
638
|
|
|
'p__phonenumber' => '42', |
639
|
|
|
'a__id' => '2', |
640
|
|
|
'a__topic' => 'ZendCon', |
641
|
|
|
], |
642
|
|
|
[ |
643
|
|
|
'u__id' => '1', |
644
|
|
|
'u__status' => 'developer', |
645
|
|
|
'sclr0' => 'ROMANB', |
646
|
|
|
'p__phonenumber' => '43', |
647
|
|
|
'a__id' => '2', |
648
|
|
|
'a__topic' => 'ZendCon', |
649
|
|
|
], |
650
|
|
|
[ |
651
|
|
|
'u__id' => '2', |
652
|
|
|
'u__status' => 'developer', |
653
|
|
|
'sclr0' => 'JWAGE', |
654
|
|
|
'p__phonenumber' => '91', |
655
|
|
|
'a__id' => '3', |
656
|
|
|
'a__topic' => 'LINQ', |
657
|
|
|
], |
658
|
|
|
[ |
659
|
|
|
'u__id' => '2', |
660
|
|
|
'u__status' => 'developer', |
661
|
|
|
'sclr0' => 'JWAGE', |
662
|
|
|
'p__phonenumber' => '91', |
663
|
|
|
'a__id' => '4', |
664
|
|
|
'a__topic' => 'PHP7', |
665
|
|
|
], |
666
|
|
|
]; |
667
|
|
|
|
668
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
669
|
|
|
$hydrator = new ObjectHydrator($this->em); |
670
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
671
|
|
|
|
672
|
|
|
self::assertCount(2, $result); |
673
|
|
|
|
674
|
|
|
self::assertInternalType('array', $result); |
|
|
|
|
675
|
|
|
self::assertInternalType('array', $result[0]); |
|
|
|
|
676
|
|
|
self::assertInternalType('array', $result[1]); |
|
|
|
|
677
|
|
|
|
678
|
|
|
self::assertInstanceOf(CmsUser::class, $result[0][$userEntityKey]); |
679
|
|
|
self::assertInstanceOf(PersistentCollection::class, $result[0][$userEntityKey]->phonenumbers); |
680
|
|
|
self::assertInstanceOf(CmsPhonenumber::class, $result[0][$userEntityKey]->phonenumbers[0]); |
681
|
|
|
self::assertInstanceOf(CmsPhonenumber::class, $result[0][$userEntityKey]->phonenumbers[1]); |
682
|
|
|
self::assertInstanceOf(PersistentCollection::class, $result[0][$userEntityKey]->articles); |
683
|
|
|
self::assertInstanceOf(CmsArticle::class, $result[0][$userEntityKey]->articles[0]); |
684
|
|
|
self::assertInstanceOf(CmsArticle::class, $result[0][$userEntityKey]->articles[1]); |
685
|
|
|
|
686
|
|
|
self::assertInstanceOf(CmsUser::class, $result[1][$userEntityKey]); |
687
|
|
|
self::assertInstanceOf(PersistentCollection::class, $result[1][$userEntityKey]->phonenumbers); |
688
|
|
|
self::assertInstanceOf(CmsPhonenumber::class, $result[1][$userEntityKey]->phonenumbers[0]); |
689
|
|
|
self::assertInstanceOf(CmsArticle::class, $result[1][$userEntityKey]->articles[0]); |
690
|
|
|
self::assertInstanceOf(CmsArticle::class, $result[1][$userEntityKey]->articles[1]); |
691
|
|
|
} |
692
|
|
|
|
693
|
|
|
/** |
694
|
|
|
* SELECT u, p, UPPER(u.name) nameUpper, a, c |
695
|
|
|
* FROM User u |
696
|
|
|
* JOIN u.phonenumbers p |
697
|
|
|
* JOIN u.articles a |
698
|
|
|
* LEFT JOIN a.comments c |
699
|
|
|
* |
700
|
|
|
* @dataProvider provideDataForUserEntityResult |
701
|
|
|
*/ |
702
|
|
|
public function testMixedQueryMultipleDeepMixedFetchJoin($userEntityKey) : void |
703
|
|
|
{ |
704
|
|
|
$rsm = new ResultSetMapping(); |
705
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u', $userEntityKey ?: null); |
706
|
|
|
$rsm->addJoinedEntityResult( |
707
|
|
|
CmsPhonenumber::class, |
708
|
|
|
'p', |
709
|
|
|
'u', |
710
|
|
|
'phonenumbers' |
711
|
|
|
); |
712
|
|
|
$rsm->addJoinedEntityResult( |
713
|
|
|
CmsArticle::class, |
714
|
|
|
'a', |
715
|
|
|
'u', |
716
|
|
|
'articles' |
717
|
|
|
); |
718
|
|
|
$rsm->addJoinedEntityResult( |
719
|
|
|
CmsComment::class, |
720
|
|
|
'c', |
721
|
|
|
'a', |
722
|
|
|
'comments' |
723
|
|
|
); |
724
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
725
|
|
|
$rsm->addFieldResult('u', 'u__status', 'status'); |
726
|
|
|
$rsm->addScalarResult('sclr0', 'nameUpper', Type::getType('string')); |
727
|
|
|
$rsm->addFieldResult('p', 'p__phonenumber', 'phonenumber'); |
728
|
|
|
$rsm->addFieldResult('a', 'a__id', 'id'); |
729
|
|
|
$rsm->addFieldResult('a', 'a__topic', 'topic'); |
730
|
|
|
$rsm->addFieldResult('c', 'c__id', 'id'); |
731
|
|
|
$rsm->addFieldResult('c', 'c__topic', 'topic'); |
732
|
|
|
|
733
|
|
|
// Faked result set |
734
|
|
|
$resultSet = [ |
735
|
|
|
//row1 |
736
|
|
|
[ |
737
|
|
|
'u__id' => '1', |
738
|
|
|
'u__status' => 'developer', |
739
|
|
|
'sclr0' => 'ROMANB', |
740
|
|
|
'p__phonenumber' => '42', |
741
|
|
|
'a__id' => '1', |
742
|
|
|
'a__topic' => 'Getting things done!', |
743
|
|
|
'c__id' => '1', |
744
|
|
|
'c__topic' => 'First!', |
745
|
|
|
], |
746
|
|
|
[ |
747
|
|
|
'u__id' => '1', |
748
|
|
|
'u__status' => 'developer', |
749
|
|
|
'sclr0' => 'ROMANB', |
750
|
|
|
'p__phonenumber' => '43', |
751
|
|
|
'a__id' => '1', |
752
|
|
|
'a__topic' => 'Getting things done!', |
753
|
|
|
'c__id' => '1', |
754
|
|
|
'c__topic' => 'First!', |
755
|
|
|
], |
756
|
|
|
[ |
757
|
|
|
'u__id' => '1', |
758
|
|
|
'u__status' => 'developer', |
759
|
|
|
'sclr0' => 'ROMANB', |
760
|
|
|
'p__phonenumber' => '42', |
761
|
|
|
'a__id' => '2', |
762
|
|
|
'a__topic' => 'ZendCon', |
763
|
|
|
'c__id' => null, |
764
|
|
|
'c__topic' => null, |
765
|
|
|
], |
766
|
|
|
[ |
767
|
|
|
'u__id' => '1', |
768
|
|
|
'u__status' => 'developer', |
769
|
|
|
'sclr0' => 'ROMANB', |
770
|
|
|
'p__phonenumber' => '43', |
771
|
|
|
'a__id' => '2', |
772
|
|
|
'a__topic' => 'ZendCon', |
773
|
|
|
'c__id' => null, |
774
|
|
|
'c__topic' => null, |
775
|
|
|
], |
776
|
|
|
[ |
777
|
|
|
'u__id' => '2', |
778
|
|
|
'u__status' => 'developer', |
779
|
|
|
'sclr0' => 'JWAGE', |
780
|
|
|
'p__phonenumber' => '91', |
781
|
|
|
'a__id' => '3', |
782
|
|
|
'a__topic' => 'LINQ', |
783
|
|
|
'c__id' => null, |
784
|
|
|
'c__topic' => null, |
785
|
|
|
], |
786
|
|
|
[ |
787
|
|
|
'u__id' => '2', |
788
|
|
|
'u__status' => 'developer', |
789
|
|
|
'sclr0' => 'JWAGE', |
790
|
|
|
'p__phonenumber' => '91', |
791
|
|
|
'a__id' => '4', |
792
|
|
|
'a__topic' => 'PHP7', |
793
|
|
|
'c__id' => null, |
794
|
|
|
'c__topic' => null, |
795
|
|
|
], |
796
|
|
|
]; |
797
|
|
|
|
798
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
799
|
|
|
$hydrator = new ObjectHydrator($this->em); |
800
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
801
|
|
|
|
802
|
|
|
self::assertCount(2, $result); |
803
|
|
|
|
804
|
|
|
self::assertInternalType('array', $result); |
|
|
|
|
805
|
|
|
self::assertInternalType('array', $result[0]); |
|
|
|
|
806
|
|
|
self::assertInternalType('array', $result[1]); |
|
|
|
|
807
|
|
|
|
808
|
|
|
self::assertInstanceOf(CmsUser::class, $result[0][$userEntityKey]); |
809
|
|
|
self::assertInstanceOf(CmsUser::class, $result[1][$userEntityKey]); |
810
|
|
|
|
811
|
|
|
// phonenumbers |
812
|
|
|
self::assertInstanceOf(PersistentCollection::class, $result[0][$userEntityKey]->phonenumbers); |
813
|
|
|
self::assertInstanceOf(CmsPhonenumber::class, $result[0][$userEntityKey]->phonenumbers[0]); |
814
|
|
|
self::assertInstanceOf(CmsPhonenumber::class, $result[0][$userEntityKey]->phonenumbers[1]); |
815
|
|
|
|
816
|
|
|
self::assertInstanceOf(PersistentCollection::class, $result[1][$userEntityKey]->phonenumbers); |
817
|
|
|
self::assertInstanceOf(CmsPhonenumber::class, $result[1][$userEntityKey]->phonenumbers[0]); |
818
|
|
|
|
819
|
|
|
// articles |
820
|
|
|
self::assertInstanceOf(PersistentCollection::class, $result[0][$userEntityKey]->articles); |
821
|
|
|
self::assertInstanceOf(CmsArticle::class, $result[0][$userEntityKey]->articles[0]); |
822
|
|
|
self::assertInstanceOf(CmsArticle::class, $result[0][$userEntityKey]->articles[1]); |
823
|
|
|
|
824
|
|
|
self::assertInstanceOf(CmsArticle::class, $result[1][$userEntityKey]->articles[0]); |
825
|
|
|
self::assertInstanceOf(CmsArticle::class, $result[1][$userEntityKey]->articles[1]); |
826
|
|
|
|
827
|
|
|
// article comments |
828
|
|
|
self::assertInstanceOf(PersistentCollection::class, $result[0][$userEntityKey]->articles[0]->comments); |
829
|
|
|
self::assertInstanceOf(CmsComment::class, $result[0][$userEntityKey]->articles[0]->comments[0]); |
830
|
|
|
|
831
|
|
|
// empty comment collections |
832
|
|
|
self::assertInstanceOf(PersistentCollection::class, $result[0][$userEntityKey]->articles[1]->comments); |
833
|
|
|
self::assertCount(0, $result[0][$userEntityKey]->articles[1]->comments); |
834
|
|
|
|
835
|
|
|
self::assertInstanceOf(PersistentCollection::class, $result[1][$userEntityKey]->articles[0]->comments); |
836
|
|
|
self::assertCount(0, $result[1][$userEntityKey]->articles[0]->comments); |
837
|
|
|
self::assertInstanceOf(PersistentCollection::class, $result[1][$userEntityKey]->articles[1]->comments); |
838
|
|
|
self::assertCount(0, $result[1][$userEntityKey]->articles[1]->comments); |
839
|
|
|
} |
840
|
|
|
|
841
|
|
|
/** |
842
|
|
|
* Tests that the hydrator does not rely on a particular order of the rows |
843
|
|
|
* in the result set. |
844
|
|
|
* |
845
|
|
|
* DQL: |
846
|
|
|
* select c, b from Doctrine\Tests\Models\Forum\ForumCategory c inner join c.boards b |
847
|
|
|
* order by c.position asc, b.position asc |
848
|
|
|
* |
849
|
|
|
* Checks whether the boards are correctly assigned to the categories. |
850
|
|
|
* |
851
|
|
|
* The 'evil' result set that confuses the object population is displayed below. |
852
|
|
|
* |
853
|
|
|
* c.id | c.position | c.name | boardPos | b.id | b.category_id (just for clarity) |
854
|
|
|
* 1 | 0 | First | 0 | 1 | 1 |
855
|
|
|
* 2 | 0 | Second | 0 | 2 | 2 <-- |
856
|
|
|
* 1 | 0 | First | 1 | 3 | 1 |
857
|
|
|
* 1 | 0 | First | 2 | 4 | 1 |
858
|
|
|
*/ |
859
|
|
|
public function testEntityQueryCustomResultSetOrder() : void |
860
|
|
|
{ |
861
|
|
|
$rsm = new ResultSetMapping(); |
862
|
|
|
$rsm->addEntityResult(ForumCategory::class, 'c'); |
863
|
|
|
$rsm->addJoinedEntityResult( |
864
|
|
|
ForumBoard::class, |
865
|
|
|
'b', |
866
|
|
|
'c', |
867
|
|
|
'boards' |
868
|
|
|
); |
869
|
|
|
$rsm->addFieldResult('c', 'c__id', 'id'); |
870
|
|
|
$rsm->addFieldResult('c', 'c__position', 'position'); |
871
|
|
|
$rsm->addFieldResult('c', 'c__name', 'name'); |
872
|
|
|
$rsm->addFieldResult('b', 'b__id', 'id'); |
873
|
|
|
$rsm->addFieldResult('b', 'b__position', 'position'); |
874
|
|
|
|
875
|
|
|
// Faked result set |
876
|
|
|
$resultSet = [ |
877
|
|
|
[ |
878
|
|
|
'c__id' => '1', |
879
|
|
|
'c__position' => '0', |
880
|
|
|
'c__name' => 'First', |
881
|
|
|
'b__id' => '1', |
882
|
|
|
'b__position' => '0', |
883
|
|
|
//'b__category_id' => '1' |
884
|
|
|
], |
885
|
|
|
[ |
886
|
|
|
'c__id' => '2', |
887
|
|
|
'c__position' => '0', |
888
|
|
|
'c__name' => 'Second', |
889
|
|
|
'b__id' => '2', |
890
|
|
|
'b__position' => '0', |
891
|
|
|
//'b__category_id' => '2' |
892
|
|
|
], |
893
|
|
|
[ |
894
|
|
|
'c__id' => '1', |
895
|
|
|
'c__position' => '0', |
896
|
|
|
'c__name' => 'First', |
897
|
|
|
'b__id' => '3', |
898
|
|
|
'b__position' => '1', |
899
|
|
|
//'b__category_id' => '1' |
900
|
|
|
], |
901
|
|
|
[ |
902
|
|
|
'c__id' => '1', |
903
|
|
|
'c__position' => '0', |
904
|
|
|
'c__name' => 'First', |
905
|
|
|
'b__id' => '4', |
906
|
|
|
'b__position' => '2', |
907
|
|
|
//'b__category_id' => '1' |
908
|
|
|
], |
909
|
|
|
]; |
910
|
|
|
|
911
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
912
|
|
|
$hydrator = new ObjectHydrator($this->em); |
913
|
|
|
/** @var ForumCategory[] $result */ |
914
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
915
|
|
|
|
916
|
|
|
self::assertCount(2, $result); |
917
|
|
|
|
918
|
|
|
self::assertInstanceOf(ForumCategory::class, $result[0]); |
919
|
|
|
self::assertInstanceOf(ForumCategory::class, $result[1]); |
920
|
|
|
|
921
|
|
|
self::assertNotSame($result[0], $result[1]); |
922
|
|
|
|
923
|
|
|
self::assertEquals(1, $result[0]->getId()); |
924
|
|
|
self::assertEquals(2, $result[1]->getId()); |
925
|
|
|
|
926
|
|
|
self::assertObjectHasAttribute('boards', $result[0]); |
927
|
|
|
self::assertCount(3, $result[0]->boards); |
928
|
|
|
|
929
|
|
|
self::assertObjectHasAttribute('boards', $result[1]); |
930
|
|
|
self::assertCount(1, $result[1]->boards); |
931
|
|
|
} |
932
|
|
|
|
933
|
|
|
/** |
934
|
|
|
* SELECT PARTIAL u.{id,name} |
935
|
|
|
* FROM Doctrine\Tests\Models\CMS\CmsUser u |
936
|
|
|
* |
937
|
|
|
* @group DDC-644 |
938
|
|
|
*/ |
939
|
|
|
public function testSkipUnknownColumns() : void |
940
|
|
|
{ |
941
|
|
|
$rsm = new ResultSetMapping(); |
942
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u'); |
943
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
944
|
|
|
$rsm->addFieldResult('u', 'u__name', 'name'); |
945
|
|
|
|
946
|
|
|
// Faked result set |
947
|
|
|
$resultSet = [ |
948
|
|
|
[ |
949
|
|
|
'u__id' => '1', |
950
|
|
|
'u__name' => 'romanb', |
951
|
|
|
'foo' => 'bar', // unknown! |
952
|
|
|
], |
953
|
|
|
]; |
954
|
|
|
|
955
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
956
|
|
|
$hydrator = new ObjectHydrator($this->em); |
957
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
958
|
|
|
|
959
|
|
|
self::assertCount(1, $result); |
960
|
|
|
self::assertInstanceOf(CmsUser::class, $result[0]); |
961
|
|
|
} |
962
|
|
|
|
963
|
|
|
/** |
964
|
|
|
* SELECT u.id, u.name |
965
|
|
|
* FROM Doctrine\Tests\Models\CMS\CmsUser u |
966
|
|
|
* |
967
|
|
|
* @dataProvider provideDataForUserEntityResult |
968
|
|
|
*/ |
969
|
|
|
public function testScalarQueryWithoutResultVariables($userEntityKey) : void |
970
|
|
|
{ |
971
|
|
|
$rsm = new ResultSetMapping(); |
972
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u', $userEntityKey ?: null); |
973
|
|
|
$rsm->addScalarResult('sclr0', 'id', Type::getType('integer')); |
974
|
|
|
$rsm->addScalarResult('sclr1', 'name', Type::getType('string')); |
975
|
|
|
|
976
|
|
|
// Faked result set |
977
|
|
|
$resultSet = [ |
978
|
|
|
[ |
979
|
|
|
'sclr0' => '1', |
980
|
|
|
'sclr1' => 'romanb', |
981
|
|
|
], |
982
|
|
|
[ |
983
|
|
|
'sclr0' => '2', |
984
|
|
|
'sclr1' => 'jwage', |
985
|
|
|
], |
986
|
|
|
]; |
987
|
|
|
|
988
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
989
|
|
|
$hydrator = new ObjectHydrator($this->em); |
990
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
991
|
|
|
|
992
|
|
|
self::assertCount(2, $result); |
993
|
|
|
|
994
|
|
|
self::assertInternalType('array', $result[0]); |
|
|
|
|
995
|
|
|
self::assertInternalType('array', $result[1]); |
|
|
|
|
996
|
|
|
|
997
|
|
|
self::assertEquals(1, $result[0]['id']); |
998
|
|
|
self::assertEquals('romanb', $result[0]['name']); |
999
|
|
|
|
1000
|
|
|
self::assertEquals(2, $result[1]['id']); |
1001
|
|
|
self::assertEquals('jwage', $result[1]['name']); |
1002
|
|
|
} |
1003
|
|
|
|
1004
|
|
|
/** |
1005
|
|
|
* SELECT p |
1006
|
|
|
* FROM Doctrine\Tests\Models\ECommerce\ECommerceProduct p |
1007
|
|
|
*/ |
1008
|
|
|
public function testCreatesProxyForLazyLoadingWithForeignKeys() : void |
1009
|
|
|
{ |
1010
|
|
|
$rsm = new ResultSetMapping(); |
1011
|
|
|
$rsm->addEntityResult(ECommerceProduct::class, 'p'); |
1012
|
|
|
$rsm->addFieldResult('p', 'p__id', 'id'); |
1013
|
|
|
$rsm->addFieldResult('p', 'p__name', 'name'); |
1014
|
|
|
$rsm->addMetaResult('p', 'p__shipping_id', 'shipping_id', false, Type::getType('integer')); |
1015
|
|
|
|
1016
|
|
|
// Faked result set |
1017
|
|
|
$resultSet = [ |
1018
|
|
|
[ |
1019
|
|
|
'p__id' => '1', |
1020
|
|
|
'p__name' => 'Doctrine Book', |
1021
|
|
|
'p__shipping_id' => 42, |
1022
|
|
|
], |
1023
|
|
|
]; |
1024
|
|
|
|
1025
|
|
|
$proxyInstance = (new LazyLoadingGhostFactory(new Configuration())) |
1026
|
|
|
->createProxy(ECommerceShipping::class, static function () { |
1027
|
|
|
self::fail('Proxy is not supposed to be lazy-loaded'); |
1028
|
|
|
}); |
1029
|
|
|
|
1030
|
|
|
// mocking the proxy factory |
1031
|
|
|
$proxyFactory = $this->createMock(ProxyFactory::class); |
1032
|
|
|
|
1033
|
|
|
$proxyFactory |
1034
|
|
|
->expects(self::once()) |
1035
|
|
|
->method('getProxy') |
1036
|
|
|
->with($this->em->getClassMetadata(ECommerceShipping::class), ['id' => 42]) |
1037
|
|
|
->willReturn($proxyInstance); |
1038
|
|
|
|
1039
|
|
|
$this->em->setProxyFactory($proxyFactory); |
1040
|
|
|
|
1041
|
|
|
// configuring lazy loading |
1042
|
|
|
$metadata = $this->em->getClassMetadata(ECommerceProduct::class); |
1043
|
|
|
$metadata->getProperty('shipping')->setFetchMode(FetchMode::LAZY); |
|
|
|
|
1044
|
|
|
|
1045
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
1046
|
|
|
$hydrator = new ObjectHydrator($this->em); |
1047
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm); |
1048
|
|
|
|
1049
|
|
|
self::assertCount(1, $result); |
1050
|
|
|
|
1051
|
|
|
self::assertInstanceOf(ECommerceProduct::class, $result[0]); |
1052
|
|
|
} |
1053
|
|
|
|
1054
|
|
|
/** |
1055
|
|
|
* SELECT p AS product |
1056
|
|
|
* FROM Doctrine\Tests\Models\ECommerce\ECommerceProduct p |
1057
|
|
|
*/ |
1058
|
|
|
public function testCreatesProxyForLazyLoadingWithForeignKeysWithAliasedProductEntity() : void |
1059
|
|
|
{ |
1060
|
|
|
$rsm = new ResultSetMapping(); |
1061
|
|
|
$rsm->addEntityResult(ECommerceProduct::class, 'p', 'product'); |
1062
|
|
|
$rsm->addFieldResult('p', 'p__id', 'id'); |
1063
|
|
|
$rsm->addFieldResult('p', 'p__name', 'name'); |
1064
|
|
|
$rsm->addMetaResult('p', 'p__shipping_id', 'shipping_id', false, Type::getType('integer')); |
1065
|
|
|
|
1066
|
|
|
// Faked result set |
1067
|
|
|
$resultSet = [ |
1068
|
|
|
[ |
1069
|
|
|
'p__id' => '1', |
1070
|
|
|
'p__name' => 'Doctrine Book', |
1071
|
|
|
'p__shipping_id' => 42, |
1072
|
|
|
], |
1073
|
|
|
]; |
1074
|
|
|
|
1075
|
|
|
$proxyInstance = (new LazyLoadingGhostFactory(new Configuration())) |
1076
|
|
|
->createProxy(ECommerceShipping::class, static function () { |
1077
|
|
|
self::fail('Proxy is not supposed to be lazy-loaded'); |
1078
|
|
|
}); |
1079
|
|
|
|
1080
|
|
|
// mocking the proxy factory |
1081
|
|
|
$proxyFactory = $this |
1082
|
|
|
->getMockBuilder(ProxyFactory::class) |
1083
|
|
|
->disableOriginalConstructor() |
1084
|
|
|
->getMock(); |
1085
|
|
|
|
1086
|
|
|
$proxyFactory |
1087
|
|
|
->expects(self::once()) |
1088
|
|
|
->method('getProxy') |
1089
|
|
|
->with($this->em->getClassMetadata(ECommerceShipping::class), ['id' => 42]) |
1090
|
|
|
->willReturn($proxyInstance); |
1091
|
|
|
|
1092
|
|
|
$this->em->setProxyFactory($proxyFactory); |
1093
|
|
|
|
1094
|
|
|
// configuring lazy loading |
1095
|
|
|
$metadata = $this->em->getClassMetadata(ECommerceProduct::class); |
1096
|
|
|
$metadata->getProperty('shipping')->setFetchMode(FetchMode::LAZY); |
1097
|
|
|
|
1098
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
1099
|
|
|
$hydrator = new ObjectHydrator($this->em); |
1100
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm); |
1101
|
|
|
|
1102
|
|
|
self::assertCount(1, $result); |
1103
|
|
|
|
1104
|
|
|
self::assertInternalType('array', $result[0]); |
|
|
|
|
1105
|
|
|
self::assertInstanceOf(ECommerceProduct::class, $result[0]['product']); |
1106
|
|
|
} |
1107
|
|
|
|
1108
|
|
|
/** |
1109
|
|
|
* SELECT PARTIAL u.{id, status}, PARTIAL a.{id, topic}, PARTIAL c.{id, topic} |
1110
|
|
|
* FROM Doctrine\Tests\Models\CMS\CmsUser u |
1111
|
|
|
* LEFT JOIN u.articles a |
1112
|
|
|
* LEFT JOIN a.comments c |
1113
|
|
|
*/ |
1114
|
|
|
public function testChainedJoinWithEmptyCollections() : void |
1115
|
|
|
{ |
1116
|
|
|
$rsm = new ResultSetMapping(); |
1117
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u'); |
1118
|
|
|
$rsm->addJoinedEntityResult( |
1119
|
|
|
CmsArticle::class, |
1120
|
|
|
'a', |
1121
|
|
|
'u', |
1122
|
|
|
'articles' |
1123
|
|
|
); |
1124
|
|
|
$rsm->addJoinedEntityResult( |
1125
|
|
|
CmsComment::class, |
1126
|
|
|
'c', |
1127
|
|
|
'a', |
1128
|
|
|
'comments' |
1129
|
|
|
); |
1130
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
1131
|
|
|
$rsm->addFieldResult('u', 'u__status', 'status'); |
1132
|
|
|
$rsm->addFieldResult('a', 'a__id', 'id'); |
1133
|
|
|
$rsm->addFieldResult('a', 'a__topic', 'topic'); |
1134
|
|
|
$rsm->addFieldResult('c', 'c__id', 'id'); |
1135
|
|
|
$rsm->addFieldResult('c', 'c__topic', 'topic'); |
1136
|
|
|
|
1137
|
|
|
// Faked result set |
1138
|
|
|
$resultSet = [ |
1139
|
|
|
//row1 |
1140
|
|
|
[ |
1141
|
|
|
'u__id' => '1', |
1142
|
|
|
'u__status' => 'developer', |
1143
|
|
|
'a__id' => null, |
1144
|
|
|
'a__topic' => null, |
1145
|
|
|
'c__id' => null, |
1146
|
|
|
'c__topic' => null, |
1147
|
|
|
], |
1148
|
|
|
[ |
1149
|
|
|
'u__id' => '2', |
1150
|
|
|
'u__status' => 'developer', |
1151
|
|
|
'a__id' => null, |
1152
|
|
|
'a__topic' => null, |
1153
|
|
|
'c__id' => null, |
1154
|
|
|
'c__topic' => null, |
1155
|
|
|
], |
1156
|
|
|
]; |
1157
|
|
|
|
1158
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
1159
|
|
|
$hydrator = new ObjectHydrator($this->em); |
1160
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
1161
|
|
|
|
1162
|
|
|
self::assertCount(2, $result); |
1163
|
|
|
|
1164
|
|
|
self::assertInstanceOf(CmsUser::class, $result[0]); |
1165
|
|
|
self::assertInstanceOf(CmsUser::class, $result[1]); |
1166
|
|
|
|
1167
|
|
|
self::assertEquals(0, $result[0]->articles->count()); |
1168
|
|
|
self::assertEquals(0, $result[1]->articles->count()); |
1169
|
|
|
} |
1170
|
|
|
|
1171
|
|
|
/** |
1172
|
|
|
* SELECT PARTIAL u.{id, status} AS user, PARTIAL a.{id, topic}, PARTIAL c.{id, topic} |
1173
|
|
|
* FROM Doctrine\Tests\Models\CMS\CmsUser u |
1174
|
|
|
* LEFT JOIN u.articles a |
1175
|
|
|
* LEFT JOIN a.comments c |
1176
|
|
|
*/ |
1177
|
|
|
public function testChainedJoinWithEmptyCollectionsWithAliasedUserEntity() : void |
1178
|
|
|
{ |
1179
|
|
|
$rsm = new ResultSetMapping(); |
1180
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u', 'user'); |
1181
|
|
|
$rsm->addJoinedEntityResult( |
1182
|
|
|
CmsArticle::class, |
1183
|
|
|
'a', |
1184
|
|
|
'u', |
1185
|
|
|
'articles' |
1186
|
|
|
); |
1187
|
|
|
$rsm->addJoinedEntityResult( |
1188
|
|
|
CmsComment::class, |
1189
|
|
|
'c', |
1190
|
|
|
'a', |
1191
|
|
|
'comments' |
1192
|
|
|
); |
1193
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
1194
|
|
|
$rsm->addFieldResult('u', 'u__status', 'status'); |
1195
|
|
|
$rsm->addFieldResult('a', 'a__id', 'id'); |
1196
|
|
|
$rsm->addFieldResult('a', 'a__topic', 'topic'); |
1197
|
|
|
$rsm->addFieldResult('c', 'c__id', 'id'); |
1198
|
|
|
$rsm->addFieldResult('c', 'c__topic', 'topic'); |
1199
|
|
|
|
1200
|
|
|
// Faked result set |
1201
|
|
|
$resultSet = [ |
1202
|
|
|
//row1 |
1203
|
|
|
[ |
1204
|
|
|
'u__id' => '1', |
1205
|
|
|
'u__status' => 'developer', |
1206
|
|
|
'a__id' => null, |
1207
|
|
|
'a__topic' => null, |
1208
|
|
|
'c__id' => null, |
1209
|
|
|
'c__topic' => null, |
1210
|
|
|
], |
1211
|
|
|
[ |
1212
|
|
|
'u__id' => '2', |
1213
|
|
|
'u__status' => 'developer', |
1214
|
|
|
'a__id' => null, |
1215
|
|
|
'a__topic' => null, |
1216
|
|
|
'c__id' => null, |
1217
|
|
|
'c__topic' => null, |
1218
|
|
|
], |
1219
|
|
|
]; |
1220
|
|
|
|
1221
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
1222
|
|
|
$hydrator = new ObjectHydrator($this->em); |
1223
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
1224
|
|
|
|
1225
|
|
|
self::assertCount(2, $result); |
1226
|
|
|
|
1227
|
|
|
self::assertInternalType('array', $result[0]); |
|
|
|
|
1228
|
|
|
self::assertInstanceOf(CmsUser::class, $result[0]['user']); |
1229
|
|
|
|
1230
|
|
|
self::assertInternalType('array', $result[1]); |
|
|
|
|
1231
|
|
|
self::assertInstanceOf(CmsUser::class, $result[1]['user']); |
1232
|
|
|
|
1233
|
|
|
self::assertEquals(0, $result[0]['user']->articles->count()); |
1234
|
|
|
self::assertEquals(0, $result[1]['user']->articles->count()); |
1235
|
|
|
} |
1236
|
|
|
|
1237
|
|
|
/** |
1238
|
|
|
* SELECT PARTIAL u.{id,status}, a.id, a.topic, c.id as cid, c.topic as ctopic |
1239
|
|
|
* FROM CmsUser u |
1240
|
|
|
* LEFT JOIN u.articles a |
1241
|
|
|
* LEFT JOIN a.comments c |
1242
|
|
|
* |
1243
|
|
|
* @todo Figure it out why this test is commented out and provide a better description in docblock |
1244
|
|
|
* @group bubu |
1245
|
|
|
* @dataProvider provideDataForUserEntityResult |
1246
|
|
|
*/ |
1247
|
|
|
/*public function testChainedJoinWithScalars($userEntityKey) : void |
1248
|
|
|
{ |
1249
|
|
|
$rsm = new ResultSetMapping; |
1250
|
|
|
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u', $userEntityKey ?: null); |
1251
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
1252
|
|
|
$rsm->addFieldResult('u', 'u__status', 'status'); |
1253
|
|
|
$rsm->addScalarResult('a__id', 'id', Type::getType('integer')); |
1254
|
|
|
$rsm->addScalarResult('a__topic', 'topic', Type::getType('string')); |
1255
|
|
|
$rsm->addScalarResult('c__id', 'cid', Type::getType('integer')); |
1256
|
|
|
$rsm->addScalarResult('c__topic', 'ctopic', Type::getType('string')); |
1257
|
|
|
|
1258
|
|
|
// Faked result set |
1259
|
|
|
$resultSet = array( |
1260
|
|
|
//row1 |
1261
|
|
|
array( |
1262
|
|
|
'u__id' => '1', |
1263
|
|
|
'u__status' => 'developer', |
1264
|
|
|
'a__id' => '1', |
1265
|
|
|
'a__topic' => 'The First', |
1266
|
|
|
'c__id' => '1', |
1267
|
|
|
'c__topic' => 'First Comment' |
1268
|
|
|
), |
1269
|
|
|
array( |
1270
|
|
|
'u__id' => '1', |
1271
|
|
|
'u__status' => 'developer', |
1272
|
|
|
'a__id' => '1', |
1273
|
|
|
'a__topic' => 'The First', |
1274
|
|
|
'c__id' => '2', |
1275
|
|
|
'c__topic' => 'Second Comment' |
1276
|
|
|
), |
1277
|
|
|
array( |
1278
|
|
|
'u__id' => '1', |
1279
|
|
|
'u__status' => 'developer', |
1280
|
|
|
'a__id' => '42', |
1281
|
|
|
'a__topic' => 'The Answer', |
1282
|
|
|
'c__id' => null, |
1283
|
|
|
'c__topic' => null |
1284
|
|
|
), |
1285
|
|
|
); |
1286
|
|
|
|
1287
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
1288
|
|
|
$hydrator = new \Doctrine\ORM\Internal\Hydration\ObjectHydrator($this->em); |
1289
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, array(Query::HINT_FORCE_PARTIAL_LOAD => true)); |
1290
|
|
|
|
1291
|
|
|
\Doctrine\Common\Util\Debug::dump($result, 3); |
1292
|
|
|
|
1293
|
|
|
self::assertCount(1, $result); |
1294
|
|
|
|
1295
|
|
|
self::assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $result[0][$userEntityKey]); // User object |
1296
|
|
|
self::assertEquals(42, $result[0]['id']); |
1297
|
|
|
self::assertEquals('The First', $result[0]['topic']); |
1298
|
|
|
self::assertEquals(1, $result[0]['cid']); |
1299
|
|
|
self::assertEquals('First Comment', $result[0]['ctopic']); |
1300
|
|
|
}*/ |
1301
|
|
|
|
1302
|
|
|
/** |
1303
|
|
|
* SELECT PARTIAL u.{id, name} |
1304
|
|
|
* FROM Doctrine\Tests\Models\CMS\CmsUser u |
1305
|
|
|
*/ |
1306
|
|
|
public function testResultIteration() : void |
1307
|
|
|
{ |
1308
|
|
|
$rsm = new ResultSetMapping(); |
1309
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u'); |
1310
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
1311
|
|
|
$rsm->addFieldResult('u', 'u__name', 'name'); |
1312
|
|
|
|
1313
|
|
|
// Faked result set |
1314
|
|
|
$resultSet = [ |
1315
|
|
|
[ |
1316
|
|
|
'u__id' => '1', |
1317
|
|
|
'u__name' => 'romanb', |
1318
|
|
|
], |
1319
|
|
|
[ |
1320
|
|
|
'u__id' => '2', |
1321
|
|
|
'u__name' => 'jwage', |
1322
|
|
|
], |
1323
|
|
|
]; |
1324
|
|
|
|
1325
|
|
|
$hydrator = new ObjectHydrator($this->em); |
1326
|
|
|
|
1327
|
|
|
$iterableResult = $hydrator->iterate( |
|
|
|
|
1328
|
|
|
new HydratorMockStatement($resultSet), |
1329
|
|
|
$rsm, |
1330
|
|
|
[Query::HINT_FORCE_PARTIAL_LOAD => true] |
1331
|
|
|
); |
1332
|
|
|
$rowNum = 0; |
1333
|
|
|
|
1334
|
|
|
while (($row = $iterableResult->next()) !== false) { |
1335
|
|
|
self::assertCount(1, $row); |
1336
|
|
|
self::assertInstanceOf(CmsUser::class, $row[0]); |
1337
|
|
|
|
1338
|
|
|
if ($rowNum === 0) { |
1339
|
|
|
self::assertEquals(1, $row[0]->id); |
1340
|
|
|
self::assertEquals('romanb', $row[0]->name); |
1341
|
|
|
} |
1342
|
|
|
|
1343
|
|
|
if ($rowNum === 1) { |
1344
|
|
|
self::assertEquals(2, $row[0]->id); |
1345
|
|
|
self::assertEquals('jwage', $row[0]->name); |
1346
|
|
|
} |
1347
|
|
|
|
1348
|
|
|
++$rowNum; |
1349
|
|
|
} |
1350
|
|
|
|
1351
|
|
|
self::assertSame(2, $rowNum); |
1352
|
|
|
|
1353
|
|
|
$iterableResult = $hydrator->getIterable( |
1354
|
|
|
new HydratorMockStatement($resultSet), |
1355
|
|
|
$rsm, |
1356
|
|
|
[Query::HINT_FORCE_PARTIAL_LOAD => true] |
1357
|
|
|
); |
1358
|
|
|
$rowNum = 0; |
1359
|
|
|
|
1360
|
|
|
foreach ($iterableResult as $user) { |
1361
|
|
|
self::assertInstanceOf(CmsUser::class, $user); |
1362
|
|
|
|
1363
|
|
|
if ($rowNum === 0) { |
1364
|
|
|
self::assertEquals(1, $user->id); |
1365
|
|
|
self::assertEquals('romanb', $user->name); |
1366
|
|
|
} |
1367
|
|
|
|
1368
|
|
|
if ($rowNum === 1) { |
1369
|
|
|
self::assertEquals(2, $user->id); |
1370
|
|
|
self::assertEquals('jwage', $user->name); |
1371
|
|
|
} |
1372
|
|
|
|
1373
|
|
|
++$rowNum; |
1374
|
|
|
} |
1375
|
|
|
|
1376
|
|
|
self::assertSame(2, $rowNum); |
1377
|
|
|
} |
1378
|
|
|
|
1379
|
|
|
/** |
1380
|
|
|
* SELECT PARTIAL u.{id, name} |
1381
|
|
|
* FROM Doctrine\Tests\Models\CMS\CmsUser u |
1382
|
|
|
*/ |
1383
|
|
|
public function testResultIterationWithAliasedUserEntity() : void |
1384
|
|
|
{ |
1385
|
|
|
$rsm = new ResultSetMapping(); |
1386
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u', 'user'); |
1387
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
1388
|
|
|
$rsm->addFieldResult('u', 'u__name', 'name'); |
1389
|
|
|
|
1390
|
|
|
// Faked result set |
1391
|
|
|
$resultSet = [ |
1392
|
|
|
[ |
1393
|
|
|
'u__id' => '1', |
1394
|
|
|
'u__name' => 'romanb', |
1395
|
|
|
], |
1396
|
|
|
[ |
1397
|
|
|
'u__id' => '2', |
1398
|
|
|
'u__name' => 'jwage', |
1399
|
|
|
], |
1400
|
|
|
]; |
1401
|
|
|
|
1402
|
|
|
$hydrator = new ObjectHydrator($this->em); |
1403
|
|
|
|
1404
|
|
|
$rowNum = 0; |
1405
|
|
|
$iterableResult = $hydrator->iterate( |
|
|
|
|
1406
|
|
|
new HydratorMockStatement($resultSet), |
1407
|
|
|
$rsm, |
1408
|
|
|
[Query::HINT_FORCE_PARTIAL_LOAD => true] |
1409
|
|
|
); |
1410
|
|
|
|
1411
|
|
|
while (($row = $iterableResult->next()) !== false) { |
1412
|
|
|
self::assertCount(1, $row); |
1413
|
|
|
self::assertArrayHasKey(0, $row); |
1414
|
|
|
self::assertArrayHasKey('user', $row[0]); |
1415
|
|
|
self::assertInstanceOf(CmsUser::class, $row[0]['user']); |
1416
|
|
|
|
1417
|
|
|
if ($rowNum === 0) { |
1418
|
|
|
self::assertEquals(1, $row[0]['user']->id); |
1419
|
|
|
self::assertEquals('romanb', $row[0]['user']->name); |
1420
|
|
|
} |
1421
|
|
|
|
1422
|
|
|
if ($rowNum === 1) { |
1423
|
|
|
self::assertEquals(2, $row[0]['user']->id); |
1424
|
|
|
self::assertEquals('jwage', $row[0]['user']->name); |
1425
|
|
|
} |
1426
|
|
|
|
1427
|
|
|
++$rowNum; |
1428
|
|
|
} |
1429
|
|
|
|
1430
|
|
|
self::assertSame(2, $rowNum); |
1431
|
|
|
|
1432
|
|
|
$rowNum = 0; |
1433
|
|
|
$iterableResult = $hydrator->getIterable( |
1434
|
|
|
new HydratorMockStatement($resultSet), |
1435
|
|
|
$rsm, |
1436
|
|
|
[Query::HINT_FORCE_PARTIAL_LOAD => true] |
1437
|
|
|
); |
1438
|
|
|
|
1439
|
|
|
foreach ($iterableResult as $row) { |
1440
|
|
|
self::assertCount(1, $row); |
1441
|
|
|
self::assertArrayHasKey('user', $row); |
1442
|
|
|
self::assertInstanceOf(CmsUser::class, $row['user']); |
1443
|
|
|
|
1444
|
|
|
if ($rowNum === 0) { |
1445
|
|
|
self::assertEquals(1, $row['user']->id); |
1446
|
|
|
self::assertEquals('romanb', $row['user']->name); |
1447
|
|
|
} |
1448
|
|
|
|
1449
|
|
|
if ($rowNum === 1) { |
1450
|
|
|
self::assertEquals(2, $row['user']->id); |
1451
|
|
|
self::assertEquals('jwage', $row['user']->name); |
1452
|
|
|
} |
1453
|
|
|
|
1454
|
|
|
++$rowNum; |
1455
|
|
|
} |
1456
|
|
|
|
1457
|
|
|
self::assertSame(2, $rowNum); |
1458
|
|
|
} |
1459
|
|
|
|
1460
|
|
|
/** |
1461
|
|
|
* Checks if multiple joined multiple-valued collections is hydrated correctly. |
1462
|
|
|
* |
1463
|
|
|
* SELECT PARTIAL u.{id, status}, PARTIAL g.{id, name}, PARTIAL p.{phonenumber} |
1464
|
|
|
* FROM Doctrine\Tests\Models\CMS\CmsUser u |
1465
|
|
|
* |
1466
|
|
|
* @group DDC-809 |
1467
|
|
|
*/ |
1468
|
|
|
public function testManyToManyHydration() : void |
1469
|
|
|
{ |
1470
|
|
|
$rsm = new ResultSetMapping(); |
1471
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u'); |
1472
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
1473
|
|
|
$rsm->addFieldResult('u', 'u__name', 'name'); |
1474
|
|
|
$rsm->addJoinedEntityResult(CmsGroup::class, 'g', 'u', 'groups'); |
1475
|
|
|
$rsm->addFieldResult('g', 'g__id', 'id'); |
1476
|
|
|
$rsm->addFieldResult('g', 'g__name', 'name'); |
1477
|
|
|
$rsm->addJoinedEntityResult(CmsPhonenumber::class, 'p', 'u', 'phonenumbers'); |
1478
|
|
|
$rsm->addFieldResult('p', 'p__phonenumber', 'phonenumber'); |
1479
|
|
|
|
1480
|
|
|
// Faked result set |
1481
|
|
|
$resultSet = [ |
1482
|
|
|
[ |
1483
|
|
|
'u__id' => '1', |
1484
|
|
|
'u__name' => 'romanb', |
1485
|
|
|
'g__id' => '3', |
1486
|
|
|
'g__name' => 'TestGroupB', |
1487
|
|
|
'p__phonenumber' => 1111, |
1488
|
|
|
], |
1489
|
|
|
[ |
1490
|
|
|
'u__id' => '1', |
1491
|
|
|
'u__name' => 'romanb', |
1492
|
|
|
'g__id' => '5', |
1493
|
|
|
'g__name' => 'TestGroupD', |
1494
|
|
|
'p__phonenumber' => 1111, |
1495
|
|
|
], |
1496
|
|
|
[ |
1497
|
|
|
'u__id' => '1', |
1498
|
|
|
'u__name' => 'romanb', |
1499
|
|
|
'g__id' => '3', |
1500
|
|
|
'g__name' => 'TestGroupB', |
1501
|
|
|
'p__phonenumber' => 2222, |
1502
|
|
|
], |
1503
|
|
|
[ |
1504
|
|
|
'u__id' => '1', |
1505
|
|
|
'u__name' => 'romanb', |
1506
|
|
|
'g__id' => '5', |
1507
|
|
|
'g__name' => 'TestGroupD', |
1508
|
|
|
'p__phonenumber' => 2222, |
1509
|
|
|
], |
1510
|
|
|
[ |
1511
|
|
|
'u__id' => '2', |
1512
|
|
|
'u__name' => 'jwage', |
1513
|
|
|
'g__id' => '2', |
1514
|
|
|
'g__name' => 'TestGroupA', |
1515
|
|
|
'p__phonenumber' => 3333, |
1516
|
|
|
], |
1517
|
|
|
[ |
1518
|
|
|
'u__id' => '2', |
1519
|
|
|
'u__name' => 'jwage', |
1520
|
|
|
'g__id' => '3', |
1521
|
|
|
'g__name' => 'TestGroupB', |
1522
|
|
|
'p__phonenumber' => 3333, |
1523
|
|
|
], |
1524
|
|
|
[ |
1525
|
|
|
'u__id' => '2', |
1526
|
|
|
'u__name' => 'jwage', |
1527
|
|
|
'g__id' => '4', |
1528
|
|
|
'g__name' => 'TestGroupC', |
1529
|
|
|
'p__phonenumber' => 3333, |
1530
|
|
|
], |
1531
|
|
|
[ |
1532
|
|
|
'u__id' => '2', |
1533
|
|
|
'u__name' => 'jwage', |
1534
|
|
|
'g__id' => '5', |
1535
|
|
|
'g__name' => 'TestGroupD', |
1536
|
|
|
'p__phonenumber' => 3333, |
1537
|
|
|
], |
1538
|
|
|
[ |
1539
|
|
|
'u__id' => '2', |
1540
|
|
|
'u__name' => 'jwage', |
1541
|
|
|
'g__id' => '2', |
1542
|
|
|
'g__name' => 'TestGroupA', |
1543
|
|
|
'p__phonenumber' => 4444, |
1544
|
|
|
], |
1545
|
|
|
[ |
1546
|
|
|
'u__id' => '2', |
1547
|
|
|
'u__name' => 'jwage', |
1548
|
|
|
'g__id' => '3', |
1549
|
|
|
'g__name' => 'TestGroupB', |
1550
|
|
|
'p__phonenumber' => 4444, |
1551
|
|
|
], |
1552
|
|
|
[ |
1553
|
|
|
'u__id' => '2', |
1554
|
|
|
'u__name' => 'jwage', |
1555
|
|
|
'g__id' => '4', |
1556
|
|
|
'g__name' => 'TestGroupC', |
1557
|
|
|
'p__phonenumber' => 4444, |
1558
|
|
|
], |
1559
|
|
|
[ |
1560
|
|
|
'u__id' => '2', |
1561
|
|
|
'u__name' => 'jwage', |
1562
|
|
|
'g__id' => '5', |
1563
|
|
|
'g__name' => 'TestGroupD', |
1564
|
|
|
'p__phonenumber' => 4444, |
1565
|
|
|
], |
1566
|
|
|
]; |
1567
|
|
|
|
1568
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
1569
|
|
|
$hydrator = new ObjectHydrator($this->em); |
1570
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
1571
|
|
|
|
1572
|
|
|
self::assertCount(2, $result); |
1573
|
|
|
|
1574
|
|
|
self::assertContainsOnly(CmsUser::class, $result); |
1575
|
|
|
|
1576
|
|
|
self::assertCount(2, $result[0]->groups); |
1577
|
|
|
self::assertCount(2, $result[0]->phonenumbers); |
1578
|
|
|
|
1579
|
|
|
self::assertCount(4, $result[1]->groups); |
1580
|
|
|
self::assertCount(2, $result[1]->phonenumbers); |
1581
|
|
|
} |
1582
|
|
|
|
1583
|
|
|
/** |
1584
|
|
|
* Checks if multiple joined multiple-valued collections is hydrated correctly. |
1585
|
|
|
* |
1586
|
|
|
* SELECT PARTIAL u.{id, status} As user, PARTIAL g.{id, name}, PARTIAL p.{phonenumber} |
1587
|
|
|
* FROM Doctrine\Tests\Models\CMS\CmsUser u |
1588
|
|
|
* |
1589
|
|
|
* @group DDC-809 |
1590
|
|
|
*/ |
1591
|
|
|
public function testManyToManyHydrationWithAliasedUserEntity() : void |
1592
|
|
|
{ |
1593
|
|
|
$rsm = new ResultSetMapping(); |
1594
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u', 'user'); |
1595
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
1596
|
|
|
$rsm->addFieldResult('u', 'u__name', 'name'); |
1597
|
|
|
$rsm->addJoinedEntityResult(CmsGroup::class, 'g', 'u', 'groups'); |
1598
|
|
|
$rsm->addFieldResult('g', 'g__id', 'id'); |
1599
|
|
|
$rsm->addFieldResult('g', 'g__name', 'name'); |
1600
|
|
|
$rsm->addJoinedEntityResult(CmsPhonenumber::class, 'p', 'u', 'phonenumbers'); |
1601
|
|
|
$rsm->addFieldResult('p', 'p__phonenumber', 'phonenumber'); |
1602
|
|
|
|
1603
|
|
|
// Faked result set |
1604
|
|
|
$resultSet = [ |
1605
|
|
|
[ |
1606
|
|
|
'u__id' => '1', |
1607
|
|
|
'u__name' => 'romanb', |
1608
|
|
|
'g__id' => '3', |
1609
|
|
|
'g__name' => 'TestGroupB', |
1610
|
|
|
'p__phonenumber' => 1111, |
1611
|
|
|
], |
1612
|
|
|
[ |
1613
|
|
|
'u__id' => '1', |
1614
|
|
|
'u__name' => 'romanb', |
1615
|
|
|
'g__id' => '5', |
1616
|
|
|
'g__name' => 'TestGroupD', |
1617
|
|
|
'p__phonenumber' => 1111, |
1618
|
|
|
], |
1619
|
|
|
[ |
1620
|
|
|
'u__id' => '1', |
1621
|
|
|
'u__name' => 'romanb', |
1622
|
|
|
'g__id' => '3', |
1623
|
|
|
'g__name' => 'TestGroupB', |
1624
|
|
|
'p__phonenumber' => 2222, |
1625
|
|
|
], |
1626
|
|
|
[ |
1627
|
|
|
'u__id' => '1', |
1628
|
|
|
'u__name' => 'romanb', |
1629
|
|
|
'g__id' => '5', |
1630
|
|
|
'g__name' => 'TestGroupD', |
1631
|
|
|
'p__phonenumber' => 2222, |
1632
|
|
|
], |
1633
|
|
|
[ |
1634
|
|
|
'u__id' => '2', |
1635
|
|
|
'u__name' => 'jwage', |
1636
|
|
|
'g__id' => '2', |
1637
|
|
|
'g__name' => 'TestGroupA', |
1638
|
|
|
'p__phonenumber' => 3333, |
1639
|
|
|
], |
1640
|
|
|
[ |
1641
|
|
|
'u__id' => '2', |
1642
|
|
|
'u__name' => 'jwage', |
1643
|
|
|
'g__id' => '3', |
1644
|
|
|
'g__name' => 'TestGroupB', |
1645
|
|
|
'p__phonenumber' => 3333, |
1646
|
|
|
], |
1647
|
|
|
[ |
1648
|
|
|
'u__id' => '2', |
1649
|
|
|
'u__name' => 'jwage', |
1650
|
|
|
'g__id' => '4', |
1651
|
|
|
'g__name' => 'TestGroupC', |
1652
|
|
|
'p__phonenumber' => 3333, |
1653
|
|
|
], |
1654
|
|
|
[ |
1655
|
|
|
'u__id' => '2', |
1656
|
|
|
'u__name' => 'jwage', |
1657
|
|
|
'g__id' => '5', |
1658
|
|
|
'g__name' => 'TestGroupD', |
1659
|
|
|
'p__phonenumber' => 3333, |
1660
|
|
|
], |
1661
|
|
|
[ |
1662
|
|
|
'u__id' => '2', |
1663
|
|
|
'u__name' => 'jwage', |
1664
|
|
|
'g__id' => '2', |
1665
|
|
|
'g__name' => 'TestGroupA', |
1666
|
|
|
'p__phonenumber' => 4444, |
1667
|
|
|
], |
1668
|
|
|
[ |
1669
|
|
|
'u__id' => '2', |
1670
|
|
|
'u__name' => 'jwage', |
1671
|
|
|
'g__id' => '3', |
1672
|
|
|
'g__name' => 'TestGroupB', |
1673
|
|
|
'p__phonenumber' => 4444, |
1674
|
|
|
], |
1675
|
|
|
[ |
1676
|
|
|
'u__id' => '2', |
1677
|
|
|
'u__name' => 'jwage', |
1678
|
|
|
'g__id' => '4', |
1679
|
|
|
'g__name' => 'TestGroupC', |
1680
|
|
|
'p__phonenumber' => 4444, |
1681
|
|
|
], |
1682
|
|
|
[ |
1683
|
|
|
'u__id' => '2', |
1684
|
|
|
'u__name' => 'jwage', |
1685
|
|
|
'g__id' => '5', |
1686
|
|
|
'g__name' => 'TestGroupD', |
1687
|
|
|
'p__phonenumber' => 4444, |
1688
|
|
|
], |
1689
|
|
|
]; |
1690
|
|
|
|
1691
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
1692
|
|
|
$hydrator = new ObjectHydrator($this->em); |
1693
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
1694
|
|
|
|
1695
|
|
|
self::assertCount(2, $result); |
1696
|
|
|
|
1697
|
|
|
self::assertInternalType('array', $result[0]); |
|
|
|
|
1698
|
|
|
self::assertInstanceOf(CmsUser::class, $result[0]['user']); |
1699
|
|
|
self::assertInternalType('array', $result[1]); |
|
|
|
|
1700
|
|
|
self::assertInstanceOf(CmsUser::class, $result[1]['user']); |
1701
|
|
|
|
1702
|
|
|
self::assertCount(2, $result[0]['user']->groups); |
1703
|
|
|
self::assertCount(2, $result[0]['user']->phonenumbers); |
1704
|
|
|
|
1705
|
|
|
self::assertCount(4, $result[1]['user']->groups); |
1706
|
|
|
self::assertCount(2, $result[1]['user']->phonenumbers); |
1707
|
|
|
} |
1708
|
|
|
|
1709
|
|
|
/** |
1710
|
|
|
* SELECT PARTIAL u.{id, status}, UPPER(u.name) as nameUpper |
1711
|
|
|
* FROM Doctrine\Tests\Models\CMS\CmsUser u |
1712
|
|
|
* |
1713
|
|
|
* @group DDC-1358 |
1714
|
|
|
* @dataProvider provideDataForUserEntityResult |
1715
|
|
|
*/ |
1716
|
|
|
public function testMissingIdForRootEntity($userEntityKey) : void |
1717
|
|
|
{ |
1718
|
|
|
$rsm = new ResultSetMapping(); |
1719
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u', $userEntityKey ?: null); |
1720
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
1721
|
|
|
$rsm->addFieldResult('u', 'u__status', 'status'); |
1722
|
|
|
$rsm->addScalarResult('sclr0', 'nameUpper', Type::getType('string')); |
1723
|
|
|
|
1724
|
|
|
// Faked result set |
1725
|
|
|
$resultSet = [ |
1726
|
|
|
//row1 |
1727
|
|
|
[ |
1728
|
|
|
'u__id' => '1', |
1729
|
|
|
'u__status' => 'developer', |
1730
|
|
|
'sclr0' => 'ROMANB', |
1731
|
|
|
], |
1732
|
|
|
[ |
1733
|
|
|
'u__id' => null, |
1734
|
|
|
'u__status' => null, |
1735
|
|
|
'sclr0' => 'ROMANB', |
1736
|
|
|
], |
1737
|
|
|
[ |
1738
|
|
|
'u__id' => '2', |
1739
|
|
|
'u__status' => 'developer', |
1740
|
|
|
'sclr0' => 'JWAGE', |
1741
|
|
|
], |
1742
|
|
|
[ |
1743
|
|
|
'u__id' => null, |
1744
|
|
|
'u__status' => null, |
1745
|
|
|
'sclr0' => 'JWAGE', |
1746
|
|
|
], |
1747
|
|
|
]; |
1748
|
|
|
|
1749
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
1750
|
|
|
$hydrator = new ObjectHydrator($this->em); |
1751
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
1752
|
|
|
|
1753
|
|
|
self::assertCount(4, $result, 'Should hydrate four results.'); |
1754
|
|
|
|
1755
|
|
|
self::assertEquals('ROMANB', $result[0]['nameUpper']); |
1756
|
|
|
self::assertEquals('ROMANB', $result[1]['nameUpper']); |
1757
|
|
|
self::assertEquals('JWAGE', $result[2]['nameUpper']); |
1758
|
|
|
self::assertEquals('JWAGE', $result[3]['nameUpper']); |
1759
|
|
|
|
1760
|
|
|
self::assertInstanceOf(CmsUser::class, $result[0][$userEntityKey]); |
1761
|
|
|
self::assertNull($result[1][$userEntityKey]); |
1762
|
|
|
|
1763
|
|
|
self::assertInstanceOf(CmsUser::class, $result[2][$userEntityKey]); |
1764
|
|
|
self::assertNull($result[3][$userEntityKey]); |
1765
|
|
|
} |
1766
|
|
|
|
1767
|
|
|
/** |
1768
|
|
|
* SELECT PARTIAL u.{id, status}, PARTIAL p.{phonenumber}, UPPER(u.name) AS nameUpper |
1769
|
|
|
* FROM Doctrine\Tests\Models\CMS\CmsUser u |
1770
|
|
|
* LEFT JOIN u.phonenumbers u |
1771
|
|
|
* |
1772
|
|
|
* @group DDC-1358 |
1773
|
|
|
* @dataProvider provideDataForUserEntityResult |
1774
|
|
|
*/ |
1775
|
|
|
public function testMissingIdForCollectionValuedChildEntity($userEntityKey) : void |
1776
|
|
|
{ |
1777
|
|
|
$rsm = new ResultSetMapping(); |
1778
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u', $userEntityKey ?: null); |
1779
|
|
|
$rsm->addJoinedEntityResult( |
1780
|
|
|
CmsPhonenumber::class, |
1781
|
|
|
'p', |
1782
|
|
|
'u', |
1783
|
|
|
'phonenumbers' |
1784
|
|
|
); |
1785
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
1786
|
|
|
$rsm->addFieldResult('u', 'u__status', 'status'); |
1787
|
|
|
$rsm->addScalarResult('sclr0', 'nameUpper', Type::getType('string')); |
1788
|
|
|
$rsm->addFieldResult('p', 'p__phonenumber', 'phonenumber'); |
1789
|
|
|
|
1790
|
|
|
// Faked result set |
1791
|
|
|
$resultSet = [ |
1792
|
|
|
//row1 |
1793
|
|
|
[ |
1794
|
|
|
'u__id' => '1', |
1795
|
|
|
'u__status' => 'developer', |
1796
|
|
|
'sclr0' => 'ROMANB', |
1797
|
|
|
'p__phonenumber' => '42', |
1798
|
|
|
], |
1799
|
|
|
[ |
1800
|
|
|
'u__id' => '1', |
1801
|
|
|
'u__status' => 'developer', |
1802
|
|
|
'sclr0' => 'ROMANB', |
1803
|
|
|
'p__phonenumber' => null, |
1804
|
|
|
], |
1805
|
|
|
[ |
1806
|
|
|
'u__id' => '2', |
1807
|
|
|
'u__status' => 'developer', |
1808
|
|
|
'sclr0' => 'JWAGE', |
1809
|
|
|
'p__phonenumber' => '91', |
1810
|
|
|
], |
1811
|
|
|
[ |
1812
|
|
|
'u__id' => '2', |
1813
|
|
|
'u__status' => 'developer', |
1814
|
|
|
'sclr0' => 'JWAGE', |
1815
|
|
|
'p__phonenumber' => null, |
1816
|
|
|
], |
1817
|
|
|
]; |
1818
|
|
|
|
1819
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
1820
|
|
|
$hydrator = new ObjectHydrator($this->em); |
1821
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
1822
|
|
|
|
1823
|
|
|
self::assertCount(2, $result); |
1824
|
|
|
|
1825
|
|
|
self::assertEquals(1, $result[0][$userEntityKey]->phonenumbers->count()); |
1826
|
|
|
self::assertEquals(1, $result[1][$userEntityKey]->phonenumbers->count()); |
1827
|
|
|
} |
1828
|
|
|
|
1829
|
|
|
/** |
1830
|
|
|
* SELECT PARTIAL u.{id, status}, PARTIAL a.{id, city}, UPPER(u.name) AS nameUpper |
1831
|
|
|
* FROM Doctrine\Tests\Models\CMS\CmsUser u |
1832
|
|
|
* JOIN u.address a |
1833
|
|
|
* |
1834
|
|
|
* @group DDC-1358 |
1835
|
|
|
* @dataProvider provideDataForUserEntityResult |
1836
|
|
|
*/ |
1837
|
|
|
public function testMissingIdForSingleValuedChildEntity($userEntityKey) : void |
1838
|
|
|
{ |
1839
|
|
|
$rsm = new ResultSetMapping(); |
1840
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u', $userEntityKey ?: null); |
1841
|
|
|
$rsm->addJoinedEntityResult( |
1842
|
|
|
CmsAddress::class, |
1843
|
|
|
'a', |
1844
|
|
|
'u', |
1845
|
|
|
'address' |
1846
|
|
|
); |
1847
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
1848
|
|
|
$rsm->addFieldResult('u', 'u__status', 'status'); |
1849
|
|
|
$rsm->addScalarResult('sclr0', 'nameUpper', Type::getType('string')); |
1850
|
|
|
$rsm->addFieldResult('a', 'a__id', 'id'); |
1851
|
|
|
$rsm->addFieldResult('a', 'a__city', 'city'); |
1852
|
|
|
$rsm->addMetaResult('a', 'user_id', 'user_id', false, Type::getType('string')); |
1853
|
|
|
|
1854
|
|
|
// Faked result set |
1855
|
|
|
$resultSet = [ |
1856
|
|
|
//row1 |
1857
|
|
|
[ |
1858
|
|
|
'u__id' => '1', |
1859
|
|
|
'u__status' => 'developer', |
1860
|
|
|
'sclr0' => 'ROMANB', |
1861
|
|
|
'a__id' => 1, |
1862
|
|
|
'a__city' => 'Berlin', |
1863
|
|
|
], |
1864
|
|
|
[ |
1865
|
|
|
'u__id' => '2', |
1866
|
|
|
'u__status' => 'developer', |
1867
|
|
|
'sclr0' => 'BENJAMIN', |
1868
|
|
|
'a__id' => null, |
1869
|
|
|
'a__city' => null, |
1870
|
|
|
], |
1871
|
|
|
]; |
1872
|
|
|
|
1873
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
1874
|
|
|
$hydrator = new ObjectHydrator($this->em); |
1875
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
1876
|
|
|
|
1877
|
|
|
self::assertCount(2, $result); |
1878
|
|
|
|
1879
|
|
|
self::assertInstanceOf(CmsAddress::class, $result[0][$userEntityKey]->address); |
1880
|
|
|
self::assertNull($result[1][$userEntityKey]->address); |
1881
|
|
|
} |
1882
|
|
|
|
1883
|
|
|
/** |
1884
|
|
|
* SELECT PARTIAL u.{id, status}, UPPER(u.name) AS nameUpper |
1885
|
|
|
* FROM Doctrine\Tests\Models\CMS\CmsUser u |
1886
|
|
|
* INDEX BY u.id |
1887
|
|
|
* |
1888
|
|
|
* @group DDC-1385 |
1889
|
|
|
* @dataProvider provideDataForUserEntityResult |
1890
|
|
|
*/ |
1891
|
|
|
public function testIndexByAndMixedResult($userEntityKey) : void |
1892
|
|
|
{ |
1893
|
|
|
$rsm = new ResultSetMapping(); |
1894
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u', $userEntityKey ?: null); |
1895
|
|
|
$rsm->addFieldResult('u', 'u__id', 'id'); |
1896
|
|
|
$rsm->addFieldResult('u', 'u__status', 'status'); |
1897
|
|
|
$rsm->addScalarResult('sclr0', 'nameUpper', Type::getType('string')); |
1898
|
|
|
$rsm->addIndexBy('u', 'id'); |
1899
|
|
|
|
1900
|
|
|
// Faked result set |
1901
|
|
|
$resultSet = [ |
1902
|
|
|
//row1 |
1903
|
|
|
[ |
1904
|
|
|
'u__id' => '1', |
1905
|
|
|
'u__status' => 'developer', |
1906
|
|
|
'sclr0' => 'ROMANB', |
1907
|
|
|
], |
1908
|
|
|
[ |
1909
|
|
|
'u__id' => '2', |
1910
|
|
|
'u__status' => 'developer', |
1911
|
|
|
'sclr0' => 'JWAGE', |
1912
|
|
|
], |
1913
|
|
|
]; |
1914
|
|
|
|
1915
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
1916
|
|
|
$hydrator = new ObjectHydrator($this->em); |
1917
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
1918
|
|
|
|
1919
|
|
|
self::assertCount(2, $result); |
1920
|
|
|
|
1921
|
|
|
self::assertArrayHasKey(1, $result); |
1922
|
|
|
self::assertEquals(1, $result[1][$userEntityKey]->id); |
1923
|
|
|
|
1924
|
|
|
self::assertArrayHasKey(2, $result); |
1925
|
|
|
self::assertEquals(2, $result[2][$userEntityKey]->id); |
1926
|
|
|
} |
1927
|
|
|
|
1928
|
|
|
/** |
1929
|
|
|
* SELECT UPPER(u.name) AS nameUpper |
1930
|
|
|
* FROM Doctrine\Tests\Models\CMS\CmsUser u |
1931
|
|
|
* |
1932
|
|
|
* @group DDC-1385 |
1933
|
|
|
* @dataProvider provideDataForUserEntityResult |
1934
|
|
|
*/ |
1935
|
|
|
public function testIndexByScalarsOnly($userEntityKey) : void |
1936
|
|
|
{ |
1937
|
|
|
$rsm = new ResultSetMapping(); |
1938
|
|
|
$rsm->addEntityResult(CmsUser::class, 'u', $userEntityKey ?: null); |
1939
|
|
|
$rsm->addScalarResult('sclr0', 'nameUpper', Type::getType('string')); |
1940
|
|
|
$rsm->addIndexByScalar('sclr0'); |
1941
|
|
|
|
1942
|
|
|
// Faked result set |
1943
|
|
|
$resultSet = [ |
1944
|
|
|
//row1 |
1945
|
|
|
['sclr0' => 'ROMANB'], |
1946
|
|
|
['sclr0' => 'JWAGE'], |
1947
|
|
|
]; |
1948
|
|
|
|
1949
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
1950
|
|
|
$hydrator = new ObjectHydrator($this->em); |
1951
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); |
1952
|
|
|
|
1953
|
|
|
self::assertEquals( |
1954
|
|
|
[ |
1955
|
|
|
'ROMANB' => ['nameUpper' => 'ROMANB'], |
1956
|
|
|
'JWAGE' => ['nameUpper' => 'JWAGE'], |
1957
|
|
|
], |
1958
|
|
|
$result |
1959
|
|
|
); |
1960
|
|
|
} |
1961
|
|
|
|
1962
|
|
|
/** |
1963
|
|
|
* @group DDC-1470 |
1964
|
|
|
* @expectedException \Doctrine\ORM\Internal\Hydration\HydrationException |
1965
|
|
|
* @expectedExceptionMessage The meta mapping for the discriminator column "c_discr" is missing for "Doctrine\Tests\Models\Company\CompanyFixContract" using the DQL alias "c". |
1966
|
|
|
*/ |
1967
|
|
|
public function testMissingMetaMappingException() : void |
1968
|
|
|
{ |
1969
|
|
|
$rsm = new ResultSetMapping(); |
1970
|
|
|
|
1971
|
|
|
$rsm->addEntityResult(CompanyFixContract::class, 'c'); |
1972
|
|
|
$rsm->addJoinedEntityResult(CompanyEmployee::class, 'e', 'c', 'salesPerson'); |
1973
|
|
|
$rsm->addFieldResult('c', 'c__id', 'id'); |
1974
|
|
|
$rsm->setDiscriminatorColumn('c', 'c_discr'); |
1975
|
|
|
|
1976
|
|
|
$resultSet = [ |
1977
|
|
|
[ |
1978
|
|
|
'c__id' => '1', |
1979
|
|
|
'c_discr' => 'fix', |
1980
|
|
|
], |
1981
|
|
|
]; |
1982
|
|
|
|
1983
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
1984
|
|
|
$hydrator = new ObjectHydrator($this->em); |
1985
|
|
|
$hydrator->hydrateAll($stmt, $rsm); |
1986
|
|
|
} |
1987
|
|
|
|
1988
|
|
|
/** |
1989
|
|
|
* @group DDC-1470 |
1990
|
|
|
* @expectedException \Doctrine\ORM\Internal\Hydration\HydrationException |
1991
|
|
|
* @expectedExceptionMessage The discriminator column "discr" is missing for "Doctrine\Tests\Models\Company\CompanyEmployee" using the DQL alias "e". |
1992
|
|
|
*/ |
1993
|
|
|
public function testMissingDiscriminatorColumnException() : void |
1994
|
|
|
{ |
1995
|
|
|
$rsm = new ResultSetMapping(); |
1996
|
|
|
|
1997
|
|
|
$rsm->addEntityResult(CompanyFixContract::class, 'c'); |
1998
|
|
|
$rsm->addJoinedEntityResult(CompanyEmployee::class, 'e', 'c', 'salesPerson'); |
1999
|
|
|
$rsm->addFieldResult('c', 'c__id', 'id'); |
2000
|
|
|
$rsm->addMetaResult('c', 'c_discr', 'discr', false, Type::getType('string')); |
2001
|
|
|
$rsm->setDiscriminatorColumn('c', 'c_discr'); |
2002
|
|
|
$rsm->addFieldResult('e', 'e__id', 'id'); |
2003
|
|
|
$rsm->addFieldResult('e', 'e__name', 'name'); |
2004
|
|
|
$rsm->addMetaResult('e ', 'e_discr', 'discr', false, Type::getType('string')); |
2005
|
|
|
$rsm->setDiscriminatorColumn('e', 'e_discr'); |
2006
|
|
|
|
2007
|
|
|
$resultSet = [ |
2008
|
|
|
[ |
2009
|
|
|
'c__id' => '1', |
2010
|
|
|
'c_discr' => 'fix', |
2011
|
|
|
'e__id' => '1', |
2012
|
|
|
'e__name' => 'Fabio B. Silva', |
2013
|
|
|
], |
2014
|
|
|
]; |
2015
|
|
|
|
2016
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
2017
|
|
|
$hydrator = new ObjectHydrator($this->em); |
2018
|
|
|
$hydrator->hydrateAll($stmt, $rsm); |
2019
|
|
|
} |
2020
|
|
|
|
2021
|
|
|
/** |
2022
|
|
|
* @group DDC-3076 |
2023
|
|
|
* @expectedException \Doctrine\ORM\Internal\Hydration\HydrationException |
2024
|
|
|
* @expectedExceptionMessage The discriminator value "subworker" is invalid. It must be one of "person", "manager", "employee". |
2025
|
|
|
*/ |
2026
|
|
|
public function testInvalidDiscriminatorValueException() : void |
2027
|
|
|
{ |
2028
|
|
|
$rsm = new ResultSetMapping(); |
2029
|
|
|
|
2030
|
|
|
$rsm->addEntityResult(CompanyPerson::class, 'p'); |
2031
|
|
|
$rsm->addFieldResult('p', 'p__id', 'id'); |
2032
|
|
|
$rsm->addFieldResult('p', 'p__name', 'name'); |
2033
|
|
|
$rsm->addMetaResult('p', 'discr', 'discr', false, Type::getType('string')); |
2034
|
|
|
$rsm->setDiscriminatorColumn('p', 'discr'); |
2035
|
|
|
|
2036
|
|
|
$resultSet = [ |
2037
|
|
|
[ |
2038
|
|
|
'p__id' => '1', |
2039
|
|
|
'p__name' => 'Fabio B. Silva', |
2040
|
|
|
'discr' => 'subworker', |
2041
|
|
|
], |
2042
|
|
|
]; |
2043
|
|
|
|
2044
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
2045
|
|
|
$hydrator = new ObjectHydrator($this->em); |
2046
|
|
|
$hydrator->hydrateAll($stmt, $rsm); |
2047
|
|
|
} |
2048
|
|
|
|
2049
|
|
|
public function testFetchJoinCollectionValuedAssociationWithDefaultArrayValue() : void |
2050
|
|
|
{ |
2051
|
|
|
$rsm = new ResultSetMapping(); |
2052
|
|
|
|
2053
|
|
|
$rsm->addEntityResult(EntityWithArrayDefaultArrayValueM2M::class, 'e1'); |
2054
|
|
|
$rsm->addJoinedEntityResult(SimpleEntity::class, 'e2', 'e1', 'collection'); |
2055
|
|
|
$rsm->addFieldResult('e1', 'a1__id', 'id'); |
2056
|
|
|
$rsm->addFieldResult('e2', 'e2__id', 'id'); |
2057
|
|
|
|
2058
|
|
|
$resultSet = [ |
2059
|
|
|
[ |
2060
|
|
|
'a1__id' => '1', |
2061
|
|
|
'e2__id' => '1', |
2062
|
|
|
], |
2063
|
|
|
]; |
2064
|
|
|
|
2065
|
|
|
$stmt = new HydratorMockStatement($resultSet); |
2066
|
|
|
$hydrator = new ObjectHydrator($this->em); |
2067
|
|
|
$result = $hydrator->hydrateAll($stmt, $rsm); |
2068
|
|
|
|
2069
|
|
|
self::assertCount(1, $result); |
2070
|
|
|
self::assertInstanceOf(EntityWithArrayDefaultArrayValueM2M::class, $result[0]); |
2071
|
|
|
self::assertInstanceOf(PersistentCollection::class, $result[0]->collection); |
2072
|
|
|
self::assertCount(1, $result[0]->collection); |
2073
|
|
|
self::assertInstanceOf(SimpleEntity::class, $result[0]->collection[0]); |
2074
|
|
|
} |
2075
|
|
|
} |
2076
|
|
|
|
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.