Skip to content

Commit d767d02

Browse files
committed
Add more tests and fix deep associations mapping
1 parent 881eb7a commit d767d02

5 files changed

Lines changed: 243 additions & 3 deletions

File tree

src/ORM/AutoHydratorRecursive.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,6 @@ protected function map(
153153
if (in_array($parentAssociation, ['hasOne', 'belongsTo'])) {
154154
if (!$parent->has($node['propertyName'])) {
155155
// create new entity
156-
//TODO: do not create entity if all fields are null
157156
$entity = $this->constructEntity($className, $row[$alias]);
158157
$parent->set($node['propertyName'], $entity);
159158
$parent->clean();
@@ -171,7 +170,6 @@ protected function map(
171170
$hash = $this->computeFieldsHash($row[$alias], $parentHash);
172171
if (!isset($this->entitiesMap[$alias][$hash])) {
173172
// create new entity
174-
//TODO: do not create entity if all fields are null
175173
$entity = $this->constructEntity($className, $row[$alias]);
176174
if ($entity !== null) {
177175
$siblings[] = $entity;

src/ORM/MappingStrategy.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ private function scanTableRecursive(string $alias): array
164164
continue;
165165
}
166166
unset($this->unknownAliases[$childAlias]);
167+
$result[$type][$childAlias]['className'] = $target->getEntityClass();
168+
$result[$type][$childAlias]['propertyName'] = $assoc->getProperty();
167169
if ($assoc instanceof BelongsToMany) {
168170
$through = $assoc->getThrough() ?? $assoc->junction();
169171
if (is_object($through)) {

src/ORM/NativeSQLMapperTrait.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
namespace Bancer\NativeQueryMapper\ORM;
66

77
use Cake\Database\StatementInterface;
8-
use Cake\ORM\Table;
98

109
trait NativeSQLMapperTrait
1110
{

tests/TestApp/Model/Table/UsersTable.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ public function initialize(array $config): void
2121
parent::initialize($config);
2222
$this->belongsTo('Countries', ['className' => CountriesTable::class]);
2323
$this->hasOne('Profiles', ['className' => ProfilesTable::class]);
24+
$this->hasMany('Articles', ['className' => ArticlesTable::class]);
2425
}
2526
}

tests/TestCase/ORM/NativeQueryMapperTest.php

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77
use PHPUnit\Framework\TestCase;
88
use Bancer\NativeQueryMapperTest\TestApp\Model\Entity\Article;
99
use Bancer\NativeQueryMapperTest\TestApp\Model\Entity\Comment;
10+
use Bancer\NativeQueryMapperTest\TestApp\Model\Entity\Country;
1011
use Bancer\NativeQueryMapperTest\TestApp\Model\Entity\Profile;
1112
use Bancer\NativeQueryMapperTest\TestApp\Model\Entity\Tag;
1213
use Bancer\NativeQueryMapperTest\TestApp\Model\Entity\User;
1314
use Bancer\NativeQueryMapperTest\TestApp\Model\Table\ArticlesTable;
1415
use Bancer\NativeQueryMapperTest\TestApp\Model\Table\CommentsTable;
16+
use Bancer\NativeQueryMapperTest\TestApp\Model\Table\CountriesTable;
1517
use Cake\ORM\Locator\LocatorAwareTrait;
1618
use Bancer\NativeQueryMapper\ORM\UnknownAliasException;
1719
use Bancer\NativeQueryMapperTest\TestApp\Model\Table\UsersTable;
@@ -343,4 +345,242 @@ public function testBelongsToManyFetchJoinTable(): void
343345
$this->assertEqualsEntities($cakeEntities, $actual);
344346
static::assertEquals($cakeEntities, $actual);*/
345347
}
348+
349+
public function testDeepAssociations(): void
350+
{
351+
/** @var \Bancer\NativeQueryMapperTest\TestApp\Model\Table\CountriesTable $CountriesTable */
352+
$CountriesTable = $this->fetchTable(CountriesTable::class);
353+
$stmt = $CountriesTable->prepareSQL("
354+
SELECT
355+
Countries.id AS Countries__id,
356+
Countries.name as Countries__name,
357+
Users.id AS Users__id,
358+
Users.username AS Users__username,
359+
Users.country_id AS Users__country_id,
360+
Profiles.id AS Profiles__id,
361+
Profiles.bio AS Profiles__bio,
362+
Articles.id AS Articles__id,
363+
Articles.title AS Articles__title,
364+
Articles.user_id AS Articles__user_id,
365+
Comments.id AS Comments__id,
366+
Comments.content AS Comments__content,
367+
Comments.article_id AS Comments__article_id
368+
FROM countries AS Countries
369+
LEFT JOIN users AS Users
370+
ON Users.country_id=Countries.id
371+
LEFT JOIN profiles AS Profiles
372+
ON Profiles.user_id=Users.id
373+
LEFT JOIN articles AS Articles
374+
ON Articles.user_id=Users.id
375+
LEFT JOIN articles_tags AS ArticlesTags
376+
ON Articles.id=ArticlesTags.article_id
377+
LEFT JOIN tags AS Tags
378+
ON Tags.id=ArticlesTags.tag_id
379+
LEFT JOIN comments AS Comments
380+
ON Comments.article_id=Articles.id
381+
");
382+
$actual = $CountriesTable->fromNativeQuery($stmt)->all();
383+
static::assertCount(5, $actual);
384+
static::assertInstanceOf(Country::class, $actual[0]);
385+
$actualUsers = $actual[0]->get('users');
386+
static::assertIsArray($actualUsers);
387+
static::assertCount(1, $actualUsers);
388+
static::assertInstanceOf(User::class, $actualUsers[0]);
389+
$actualArticles = $actualUsers[0]->get('articles');
390+
static::assertIsArray($actualArticles);
391+
static::assertCount(1, $actualArticles);
392+
static::assertInstanceOf(Article::class, $actualArticles[0]);
393+
$actualComments = $actualArticles[0]->get('comments');
394+
static::assertIsArray($actualComments);
395+
static::assertCount(2, $actualComments);
396+
static::assertInstanceOf(Comment::class, $actualComments[0]);
397+
$expected = [
398+
'id' => 1,
399+
'name' => 'USA',
400+
'users' => [
401+
[
402+
'id' => 1,
403+
'username' => 'alice',
404+
'country_id' => 1,
405+
'profile' => [
406+
'id' => 1,
407+
'bio' => 'Bio Alice',
408+
],
409+
'articles' => [
410+
[
411+
'id' => 1,
412+
'title' => 'Article 1',
413+
'user_id' => 1,
414+
'comments' => [
415+
[
416+
'id' => 1,
417+
'content' => 'Comment 1',
418+
'article_id' => 1,
419+
],
420+
[
421+
'id' => 2,
422+
'content' => 'Comment 2',
423+
'article_id' => 1,
424+
],
425+
],
426+
],
427+
],
428+
],
429+
],
430+
];
431+
static::assertSame($expected, $actual[0]->toArray());
432+
$cakeEntities = $CountriesTable->find()
433+
->select(['Countries.id', 'Countries.name'])
434+
->contain([
435+
'Users' => [
436+
'fields' => ['Users.id', 'Users.username', 'Users.country_id'],
437+
'Profiles' => [
438+
'fields' => ['Profiles.id', 'Profiles.bio'],
439+
],
440+
'Articles' => [
441+
'fields' => ['Articles.id', 'Articles.title', 'Articles.user_id'],
442+
'Comments' => [
443+
'fields' => ['Comments.id', 'Comments.content', 'Comments.article_id'],
444+
],
445+
],
446+
],
447+
])
448+
->toArray();
449+
$this->assertEqualsEntities($cakeEntities, $actual);
450+
}
451+
452+
public function testDeepAssociationsWithBelongsToMany(): void
453+
{
454+
/** @var \Bancer\NativeQueryMapperTest\TestApp\Model\Table\CountriesTable $CountriesTable */
455+
$CountriesTable = $this->fetchTable(CountriesTable::class);
456+
$stmt = $CountriesTable->prepareSQL("
457+
SELECT
458+
Countries.id AS Countries__id,
459+
Countries.name as Countries__name,
460+
Users.id AS Users__id,
461+
Users.username AS Users__username,
462+
Profiles.id AS Profiles__id,
463+
Profiles.bio AS Profiles__bio,
464+
Articles.id AS Articles__id,
465+
Articles.title AS Articles__title,
466+
Tags.id AS Tags__id,
467+
Tags.name AS Tags__name,
468+
ArticlesTags.id AS ArticlesTags__id,
469+
ArticlesTags.article_id AS ArticlesTags__article_id,
470+
ArticlesTags.tag_id AS ArticlesTags__tag_id,
471+
Comments.id AS Comments__id,
472+
Comments.content AS Comments__content
473+
FROM countries AS Countries
474+
LEFT JOIN users AS Users
475+
ON Users.country_id=Countries.id
476+
LEFT JOIN profiles AS Profiles
477+
ON Profiles.user_id=Users.id
478+
LEFT JOIN articles AS Articles
479+
ON Articles.user_id=Users.id
480+
LEFT JOIN articles_tags AS ArticlesTags
481+
ON Articles.id=ArticlesTags.article_id
482+
LEFT JOIN tags AS Tags
483+
ON Tags.id=ArticlesTags.tag_id
484+
LEFT JOIN comments AS Comments
485+
ON Comments.article_id=Articles.id
486+
");
487+
$actual = $CountriesTable->fromNativeQuery($stmt)->all();
488+
static::assertCount(5, $actual);
489+
static::assertInstanceOf(Country::class, $actual[0]);
490+
$actualUsers = $actual[0]->get('users');
491+
static::assertIsArray($actualUsers);
492+
static::assertCount(1, $actualUsers);
493+
static::assertInstanceOf(User::class, $actualUsers[0]);
494+
$actualArticles = $actualUsers[0]->get('articles');
495+
static::assertIsArray($actualArticles);
496+
static::assertCount(1, $actualArticles);
497+
static::assertInstanceOf(Article::class, $actualArticles[0]);
498+
$actualComments = $actualArticles[0]->get('comments');
499+
static::assertIsArray($actualComments);
500+
static::assertCount(2, $actualComments);
501+
static::assertInstanceOf(Comment::class, $actualComments[0]);
502+
$actualTags = $actualArticles[0]->get('tags');
503+
static::assertIsArray($actualTags);
504+
static::assertCount(2, $actualTags);
505+
static::assertInstanceOf(Tag::class, $actualTags[0]);
506+
$expected = [
507+
'id' => 1,
508+
'name' => 'USA',
509+
'users' => [
510+
[
511+
'id' => 1,
512+
'username' => 'alice',
513+
'profile' => [
514+
'id' => 1,
515+
'bio' => 'Bio Alice',
516+
],
517+
'articles' => [
518+
[
519+
'id' => 1,
520+
'title' => 'Article 1',
521+
'comments' => [
522+
[
523+
'id' => 1,
524+
'content' => 'Comment 1',
525+
],
526+
[
527+
'id' => 2,
528+
'content' => 'Comment 2',
529+
],
530+
],
531+
'tags' => [
532+
[
533+
'id' => 1,
534+
'name' => 'Tech',
535+
'articles_tag' =>
536+
[
537+
'id' => 1,
538+
'article_id' => 1,
539+
'tag_id' => 1,
540+
],
541+
],
542+
[
543+
'id' => 2,
544+
'name' => 'Food',
545+
'articles_tag' =>
546+
[
547+
'id' => 2,
548+
'article_id' => 1,
549+
'tag_id' => 2,
550+
],
551+
],
552+
],
553+
],
554+
],
555+
],
556+
],
557+
];
558+
static::assertSame($expected, $actual[0]->toArray());
559+
/*$cakeEntities = $CountriesTable->find()
560+
->select(['Countries.id', 'Countries.name'])
561+
->contain([
562+
'Users' => [
563+
'fields' => ['Users.id', 'Users.username', 'Users.country_id'],
564+
'Profiles' => [
565+
'fields' => ['Profiles.id', 'Profiles.bio'],
566+
],
567+
'Articles' => [
568+
'fields' => ['Articles.id', 'Articles.title', 'Articles.user_id'],
569+
'Tags' => [
570+
'fields' => ['Tags.id', 'Tags.name'],
571+
'ArticlesTags' => [
572+
'fields' => ['ArticlesTags.id', 'ArticlesTags.article_id', 'ArticlesTags.tag_id'],
573+
],
574+
],
575+
'Comments' => [
576+
'fields' => ['Comments.id', 'Comments.content', 'Comments.article_id'],
577+
],
578+
],
579+
],
580+
])
581+
->toArray();
582+
static::assertSame($cakeEntities[0]->toArray(), $actual[0]->toArray());
583+
$this->assertEqualsEntities($cakeEntities, $actual);
584+
static::assertEquals($cakeEntities, $actual);*/
585+
}
346586
}

0 commit comments

Comments
 (0)