From 0b70e4bdeec187c4df186dfc4339196b03e8d126 Mon Sep 17 00:00:00 2001 From: Alexander Berezinsky Date: Tue, 28 May 2019 11:21:10 +0200 Subject: [PATCH 1/5] Added the NestedRelation --- lib/Mapper.php | 14 +++ lib/Relation/NestedRelation.php | 179 ++++++++++++++++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 lib/Relation/NestedRelation.php diff --git a/lib/Mapper.php b/lib/Mapper.php index 03ae52d..6a78238 100644 --- a/lib/Mapper.php +++ b/lib/Mapper.php @@ -2,6 +2,7 @@ namespace Spot; use Doctrine\DBAL\Types\Type; +use Spot\Relation\RelationAbstract; /** * Base DataMapper @@ -218,6 +219,19 @@ public function belongsTo(EntityInterface $entity, $foreignEntity, $localKey) return new Relation\BelongsTo($this, $foreignEntity, $foreignKey, $localKey, $entity->$localKey); } + /** + * Relation: NestedRelation + * + * @param RelationAbstract $relationObject + * @param RelationAbstract $parentRelationObject + * + * @return Relation\NestedRelation + */ + public function nestedRelation(RelationAbstract $relationObject, RelationAbstract $parentRelationObject) + { + return new Relation\NestedRelation($relationObject, $parentRelationObject); + } + /** * Prepare entity and load necessary objects on it * @param EntityInterface $entity diff --git a/lib/Relation/NestedRelation.php b/lib/Relation/NestedRelation.php new file mode 100644 index 0000000..9d60c59 --- /dev/null +++ b/lib/Relation/NestedRelation.php @@ -0,0 +1,179 @@ +relationObject = $relationObject; + $this->parentRelationObject = $parentRelationObject; + } + + /** + * Set identity values from given collection + * + * @param \Spot\Entity\Collection + */ + public function identityValuesFromCollection(Collection $collection) + { + // This method is not used here + } + + /** + * Build query object + * + * @return \Spot\Query + */ + protected function buildQuery() + { + return $this->relationObject->buildQuery(); + } + + /** + * Map relation results to original collection of entities + * + * @param string Relation name + * @param \Spot\Entity\Collection Collection of original entities to map results of query back to + * + * @return \Spot\Entity\Collection + * + * @throws \Exception + */ + public function eagerLoadOnCollection($relationName, Collection $collection) + { + $relationNames = explode('.', $relationName); + $this->relationName = array_pop($relationNames); + $this->parentRelationName = array_pop($relationNames); + + $this->createRelationCollection($collection); + + $filledRelationCollection = $this->relationObject->eagerLoadOnCollection($this->relationName, $this->relationCollection); + + if (!empty($this->relationCollectionReversedIdentities)) { + $result = []; + foreach ($filledRelationCollection as $ent) { + $result[$this->relationCollectionReversedIdentities[$ent->getId()]][] = $ent; + } + $filledRelationCollection = $result; + } + + return $this->addFilledCollection($collection, $filledRelationCollection); + } + + /** + * @param $collection + * @param $filledRelationCollection + * + * @return mixed + */ + public function addFilledCollection($collection, $filledRelationCollection) + { + $parentCollection = $collection; + if ($this->parentRelationObject instanceof NestedRelation) { + $parentCollection = $this->parentRelationObject->relationCollection; + } + + foreach($parentCollection as $entity) { + $entity->relation($this->parentRelationName, $filledRelationCollection[$entity->getId()]); + } + + if ($this->parentRelationObject instanceof NestedRelation) { + return $this->parentRelationObject->addFilledCollection($collection, $parentCollection); + } + + return $parentCollection; + } + + /** + * @param Collection $collection + */ + public function createRelationCollection(Collection $collection) + { + if ($this->parentRelationObject instanceof NestedRelation) { + $collection = $this->parentRelationObject->relationCollection; + } + $relationCollection = []; + $resultsIdentities = []; + foreach($collection as $entity) { + $relatedEntity = $entity->relation($this->parentRelationName); + if ($relatedEntity instanceof Collection) { + foreach ($relatedEntity as $childEntity) { + $relationCollection[] = $childEntity; + $resultsIdentities[] = $childEntity->getId(); + $this->relationCollectionReversedIdentities[$childEntity->getId()] = $entity->getId(); + } + } else { + $relationCollection[$entity->getId()] = $relatedEntity; + $resultsIdentities[] = $relatedEntity->getId(); + } + } + $this->relationCollection = new Collection($relationCollection, $resultsIdentities); + $this->relationObject->identityValuesFromCollection($this->relationCollection); + } + + + /** + * Save related entities + * + * @param EntityInterface $entity Entity to save relation from + * @param string $relationName Name of the relation to save + * @param array $options Options to pass to the mappers + * + * @return boolean + * + * @throws \Exception + */ + public function save(EntityInterface $entity, $relationName, $options = []) + { + return true; // Not needed to be implemented + } +} From bdd941cb3ddac05ebc4e13808c78e4d77eb091d0 Mon Sep 17 00:00:00 2001 From: alexberezinsky Date: Wed, 19 Jun 2019 10:14:01 +0200 Subject: [PATCH 2/5] Sample test --- lib/MapperInterface.php | 9 +++ tests/CRUD.php | 2 +- tests/Entity/Post.php | 5 ++ tests/Entity/Post/UserComment.php | 37 ++++++++++++ tests/Entity/User.php | 27 +++++++++ tests/NestedRelation.php | 97 +++++++++++++++++++++++++++++++ 6 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 tests/Entity/Post/UserComment.php create mode 100644 tests/Entity/User.php create mode 100644 tests/NestedRelation.php diff --git a/lib/MapperInterface.php b/lib/MapperInterface.php index d5054bb..c8ffdf7 100644 --- a/lib/MapperInterface.php +++ b/lib/MapperInterface.php @@ -1,6 +1,8 @@ hasMany($entity, 'SpotTest\Entity\Post\UserComment', 'post_id'); + $userRelation = UserComment::relations($mapper, $entity)['user']; return [ 'tags' => $mapper->hasManyThrough($entity, 'SpotTest\Entity\Tag', 'SpotTest\Entity\PostTag', 'tag_id', 'post_id'), 'comments' => $mapper->hasMany($entity, 'SpotTest\Entity\Post\Comment', 'post_id')->order(['date_created' => 'ASC']), 'polymorphic_comments' => $mapper->hasMany($entity, 'SpotTest\Entity\PolymorphicComment', 'item_id')->where(['item_type' => 'post']), + 'user_comments' => $userCommentsRelation, + 'user_comments.user' => $mapper->nestedRelation($userRelation, $userCommentsRelation), 'author' => $mapper->belongsTo($entity, 'SpotTest\Entity\Author', 'author_id') ]; } diff --git a/tests/Entity/Post/UserComment.php b/tests/Entity/Post/UserComment.php new file mode 100644 index 0000000..4b95ca8 --- /dev/null +++ b/tests/Entity/Post/UserComment.php @@ -0,0 +1,37 @@ + ['type' => 'integer', 'primary' => true, 'autoincrement' => true], + 'post_id' => ['type' => 'integer', 'index' => true, 'required' => true], + 'user_id' => ['type' => 'integer', 'index' => true, 'required' => true], + 'body' => ['type' => 'text', 'required' => true], + 'date_created' => ['type' => 'datetime'] + ]; + } + + public static function relations(MapperInterface $mapper, EntityInterface $entity) + { + return [ + 'post' => $mapper->belongsTo($entity, 'SpotTest\Entity\Post', 'post_id'), + 'user' => $mapper->belongsTo($entity, 'SpotTest\Entity\User', 'user_id') + ]; + } +} diff --git a/tests/Entity/User.php b/tests/Entity/User.php new file mode 100644 index 0000000..c336a4e --- /dev/null +++ b/tests/Entity/User.php @@ -0,0 +1,27 @@ + ['type' => 'integer', 'primary' => true, 'autoincrement' => true], + 'email' => ['type' => 'string', 'required' => true, 'unique' => true, + 'validation' => [ + 'email', + 'length' => [4, 255] + ] + ], // Unique + 'password' => ['type' => 'text', 'required' => true], + 'date_created' => ['type' => 'datetime', 'value' => new \DateTime()] + ]; + } +} diff --git a/tests/NestedRelation.php b/tests/NestedRelation.php new file mode 100644 index 0000000..6b36f0d --- /dev/null +++ b/tests/NestedRelation.php @@ -0,0 +1,97 @@ +migrate(); + } + + // Fixtures for this test suite + + // Author + $authorMapper = test_spot_mapper('SpotTest\Entity\Author'); + $author = $authorMapper->create([ + 'id' => 123, + 'email' => 'test123@test.com', + 'password' => 'password123', + 'is_admin' => false + ]); + + // User + $users = []; + $usersCount = 2; + $userMapper = test_spot_mapper('SpotTest\Entity\User'); + for ($i = 1; $i <= $usersCount; $i++) { + $users[] = $userMapper->create([ + 'email' => "test_$i@test.com", + 'password' => 'password' + ]); + } + + // Posts + $posts = []; + $postsCount = 3; + $mapper = test_spot_mapper('SpotTest\Entity\Post'); + for ($i = 1; $i <= $postsCount; $i++) { + $posts[] = $mapper->create([ + 'title' => "Eager Loading Test Post $i", + 'body' => "Eager Loading Test Post Content Here $i", + 'author_id' => $author->id + ]); + } + + // 3 comments for each post + foreach ($posts as $post) { + $comments = []; + $commentCount = 3; + $commentMapper = test_spot_mapper('SpotTest\Entity\Post\UserComment'); + for ($i = 1; $i <= $commentCount; $i++) { + $comments[] = $commentMapper->create([ + 'post_id' => $post->id, + 'user_id' => $i % $usersCount + 1, + 'body' => "This is a test comment $i. Yay!" + ]); + } + } + } + + public static function tearDownAfterClass() + { + foreach (self::$entities as $entity) { + test_spot_mapper('\SpotTest\Entity\\' . $entity)->dropTable(); + } + } + + public function testEagerLoad() + { + $mapper = test_spot_mapper('\SpotTest\Entity\Post'); + + // Set SQL logger + $logger = new \Doctrine\DBAL\Logging\DebugStack(); + $mapper->connection()->getConfiguration()->setSQLLogger($logger); + + $startCount = count($logger->queries); + + $posts = $mapper->all()->with('user_comments', 'user_comments.user'); + foreach ($posts as $post) { + foreach ($post->user_comments as $comment) { + $user = $comment->user; + $user->id; + // Do nothing - just had to iterate to execute the queries + $this->assertEquals($post->id, $comment->post_id); + } + } + $endCount = count($logger->queries); + + // Eager-loaded relation should be only 2 queries + $this->assertEquals($startCount+2, $endCount); + } +} From 51238241ee7a206167af6cf369bcf54f99e05068 Mon Sep 17 00:00:00 2001 From: alexberezinsky Date: Tue, 25 Jun 2019 15:54:12 +0200 Subject: [PATCH 3/5] A --- lib/Relation/NestedRelation.php | 16 ++++++++----- tests/NestedRelation.php | 40 ++++++++++++++++++++++----------- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/lib/Relation/NestedRelation.php b/lib/Relation/NestedRelation.php index 9d60c59..3c375d2 100644 --- a/lib/Relation/NestedRelation.php +++ b/lib/Relation/NestedRelation.php @@ -101,7 +101,9 @@ public function eagerLoadOnCollection($relationName, Collection $collection) if (!empty($this->relationCollectionReversedIdentities)) { $result = []; foreach ($filledRelationCollection as $ent) { - $result[$this->relationCollectionReversedIdentities[$ent->getId()]][] = $ent; + if (isset($this->relationCollectionReversedIdentities[$ent->primaryKey()])) { + $result[$this->relationCollectionReversedIdentities[$ent->primaryKey()]][] = $ent; + } } $filledRelationCollection = $result; } @@ -123,7 +125,9 @@ public function addFilledCollection($collection, $filledRelationCollection) } foreach($parentCollection as $entity) { - $entity->relation($this->parentRelationName, $filledRelationCollection[$entity->getId()]); + if (isset($filledRelationCollection[$entity->primaryKey()])) { + $entity->relation($this->parentRelationName, $filledRelationCollection[$entity->primaryKey()]); + } } if ($this->parentRelationObject instanceof NestedRelation) { @@ -148,12 +152,12 @@ public function createRelationCollection(Collection $collection) if ($relatedEntity instanceof Collection) { foreach ($relatedEntity as $childEntity) { $relationCollection[] = $childEntity; - $resultsIdentities[] = $childEntity->getId(); - $this->relationCollectionReversedIdentities[$childEntity->getId()] = $entity->getId(); + $resultsIdentities[] = $childEntity->primaryKey(); + $this->relationCollectionReversedIdentities[$childEntity->primaryKey()] = $entity->primaryKey(); } } else { - $relationCollection[$entity->getId()] = $relatedEntity; - $resultsIdentities[] = $relatedEntity->getId(); + $relationCollection[$entity->primaryKey()] = $relatedEntity; + $resultsIdentities[] = $relatedEntity->primaryKey(); } } $this->relationCollection = new Collection($relationCollection, $resultsIdentities); diff --git a/tests/NestedRelation.php b/tests/NestedRelation.php index 6b36f0d..2ee0c48 100644 --- a/tests/NestedRelation.php +++ b/tests/NestedRelation.php @@ -16,7 +16,7 @@ public static function setupBeforeClass() // Fixtures for this test suite - // Author + // 1 Author $authorMapper = test_spot_mapper('SpotTest\Entity\Author'); $author = $authorMapper->create([ 'id' => 123, @@ -25,9 +25,9 @@ public static function setupBeforeClass() 'is_admin' => false ]); - // User + // 4 Users $users = []; - $usersCount = 2; + $usersCount = 4; $userMapper = test_spot_mapper('SpotTest\Entity\User'); for ($i = 1; $i <= $usersCount; $i++) { $users[] = $userMapper->create([ @@ -36,9 +36,9 @@ public static function setupBeforeClass() ]); } - // Posts + // 10 Posts $posts = []; - $postsCount = 3; + $postsCount = 10; $mapper = test_spot_mapper('SpotTest\Entity\Post'); for ($i = 1; $i <= $postsCount; $i++) { $posts[] = $mapper->create([ @@ -48,10 +48,10 @@ public static function setupBeforeClass() ]); } - // 3 comments for each post + // 10 comments for each post foreach ($posts as $post) { $comments = []; - $commentCount = 3; + $commentCount = 10; $commentMapper = test_spot_mapper('SpotTest\Entity\Post\UserComment'); for ($i = 1; $i <= $commentCount; $i++) { $comments[] = $commentMapper->create([ @@ -70,7 +70,10 @@ public static function tearDownAfterClass() } } - public function testEagerLoad() + /** + * @dataProvider testEagerLoadDataProvider() + */ + public function testEagerLoad($relations, $expectedTotalQueries) { $mapper = test_spot_mapper('\SpotTest\Entity\Post'); @@ -80,18 +83,29 @@ public function testEagerLoad() $startCount = count($logger->queries); - $posts = $mapper->all()->with('user_comments', 'user_comments.user'); + $posts = $mapper->all()->with($relations); foreach ($posts as $post) { foreach ($post->user_comments as $comment) { $user = $comment->user; - $user->id; - // Do nothing - just had to iterate to execute the queries - $this->assertEquals($post->id, $comment->post_id); + // Lets check that we have the correct user for each comment + $this->assertEquals($user->id, $comment->user_id); } } $endCount = count($logger->queries); // Eager-loaded relation should be only 2 queries - $this->assertEquals($startCount+2, $endCount); + $this->assertEquals($startCount+$expectedTotalQueries, $endCount); + } + + public function testEagerLoadDataProvider() + { + return [ + [ + ['user_comments'], 102 + ], + [ + ['user_comments', 'user_coments.user'], 3 + ] + ]; } } From 19836602f60025301745553670247ebe6b60d4fe Mon Sep 17 00:00:00 2001 From: alexberezinsky Date: Tue, 25 Jun 2019 18:47:50 +0200 Subject: [PATCH 4/5] A --- lib/Mapper.php | 27 +++++++++++++++++++++++++-- lib/MapperInterface.php | 3 +++ lib/Relation/NestedRelation.php | 15 +++++++++------ tests/Entity/Post.php | 5 +---- tests/NestedRelation.php | 29 ++++++++++++++++++++++++++++- 5 files changed, 66 insertions(+), 13 deletions(-) diff --git a/lib/Mapper.php b/lib/Mapper.php index 6a78238..ac13391 100644 --- a/lib/Mapper.php +++ b/lib/Mapper.php @@ -222,10 +222,10 @@ public function belongsTo(EntityInterface $entity, $foreignEntity, $localKey) /** * Relation: NestedRelation * - * @param RelationAbstract $relationObject + * @param RelationAbstract $relationObject , * @param RelationAbstract $parentRelationObject * - * @return Relation\NestedRelation + * @return Relation\NestedRelation|bool */ public function nestedRelation(RelationAbstract $relationObject, RelationAbstract $parentRelationObject) { @@ -459,6 +459,8 @@ protected function with($collection, $entityName, $with = []) return $collection; } + $relationObjects = []; + foreach ($with as $relationName) { // We only need a single entity from the collection, because we're // going to modify the query to pass in an array of all the @@ -472,6 +474,25 @@ protected function with($collection, $entityName, $with = []) $relationObject = $singleEntity->relation($relationName); + // Handle nested relations + if ($relationObject === false) { + $relationNames = explode('.', $relationName); + if (count($relationNames) > 1) { + $finalRelationName = array_pop($relationNames); + $parentRelationName = implode('.', $relationNames); + if (!isset($relationObjects[$parentRelationName])) { + throw new \InvalidArgumentException("Nested relation exception: parent relation is not loaded:'" . $parentRelationName . "'"); + } + $parentRelation = $relationObjects[$parentRelationName]; + $parentRelationEntity = $parentRelation->entityName(); + if( !isset($parentRelationEntity::relations($this, (new $parentRelationEntity))[$finalRelationName])) { + throw new \InvalidArgumentException("Nested relation exception: target relation '" . $finalRelationName . "' doesn't exist in Entity '" . $parentRelationEntity . "'"); + } + $targetRelation = $parentRelationEntity::relations($this, (new $parentRelationEntity))[$finalRelationName]; + $relationObject = $this->nestedRelation($targetRelation, $parentRelation); + } + } + // Ensure we have a valid relation name if ($relationObject === false) { throw new Exception("Invalid relation name eager-loaded in 'with' clause: No relation on $entityName with name '$relationName'"); @@ -492,6 +513,8 @@ protected function with($collection, $entityName, $with = []) // Eager-load relation results back to collection $collection = $relationObject->eagerLoadOnCollection($relationName, $collection); + + $relationObjects[$relationName] = $relationObject; } $eventEmitter->emit('afterWith', [$this, $collection, $with]); diff --git a/lib/MapperInterface.php b/lib/MapperInterface.php index c8ffdf7..1cff5bf 100644 --- a/lib/MapperInterface.php +++ b/lib/MapperInterface.php @@ -98,6 +98,9 @@ public function belongsTo(EntityInterface $entity, $foreignEntity, $localKey); * Relation: NestedRelation * * Loading multilevel relations + * + * @param RelationAbstract $relationObject , + * @param RelationAbstract $parentRelationObject */ public function nestedRelation(RelationAbstract $relationObject, RelationAbstract $parentRelationObject); diff --git a/lib/Relation/NestedRelation.php b/lib/Relation/NestedRelation.php index 3c375d2..60cebd5 100644 --- a/lib/Relation/NestedRelation.php +++ b/lib/Relation/NestedRelation.php @@ -33,6 +33,11 @@ class NestedRelation extends RelationAbstract */ protected $relationName; + /** + * @var string + */ + protected $entityName; + /* * @var Collection */ @@ -56,6 +61,7 @@ public function __construct ( { $this->relationObject = $relationObject; $this->parentRelationObject = $parentRelationObject; + $this->entityName = $relationObject->entityName(); } /** @@ -65,17 +71,16 @@ public function __construct ( */ public function identityValuesFromCollection(Collection $collection) { - // This method is not used here + throw new \BadMethodCallException("This method is not implemented in NestedRelation class"); } /** * Build query object * - * @return \Spot\Query */ protected function buildQuery() { - return $this->relationObject->buildQuery(); + throw new \BadMethodCallException("This method is not implemented in NestedRelation class"); } /** @@ -172,12 +177,10 @@ public function createRelationCollection(Collection $collection) * @param string $relationName Name of the relation to save * @param array $options Options to pass to the mappers * - * @return boolean - * * @throws \Exception */ public function save(EntityInterface $entity, $relationName, $options = []) { - return true; // Not needed to be implemented + throw new \BadMethodCallException("This method is not implemented in NestedRelation class"); } } diff --git a/tests/Entity/Post.php b/tests/Entity/Post.php index 604f09e..24df142 100644 --- a/tests/Entity/Post.php +++ b/tests/Entity/Post.php @@ -35,14 +35,11 @@ public static function fields() public static function relations(MapperInterface $mapper, EntityInterface $entity) { - $userCommentsRelation = $mapper->hasMany($entity, 'SpotTest\Entity\Post\UserComment', 'post_id'); - $userRelation = UserComment::relations($mapper, $entity)['user']; return [ 'tags' => $mapper->hasManyThrough($entity, 'SpotTest\Entity\Tag', 'SpotTest\Entity\PostTag', 'tag_id', 'post_id'), 'comments' => $mapper->hasMany($entity, 'SpotTest\Entity\Post\Comment', 'post_id')->order(['date_created' => 'ASC']), 'polymorphic_comments' => $mapper->hasMany($entity, 'SpotTest\Entity\PolymorphicComment', 'item_id')->where(['item_type' => 'post']), - 'user_comments' => $userCommentsRelation, - 'user_comments.user' => $mapper->nestedRelation($userRelation, $userCommentsRelation), + 'user_comments' => $mapper->hasMany($entity, 'SpotTest\Entity\Post\UserComment', 'post_id'), 'author' => $mapper->belongsTo($entity, 'SpotTest\Entity\Author', 'author_id') ]; } diff --git a/tests/NestedRelation.php b/tests/NestedRelation.php index 2ee0c48..c67c603 100644 --- a/tests/NestedRelation.php +++ b/tests/NestedRelation.php @@ -104,8 +104,35 @@ public function testEagerLoadDataProvider() ['user_comments'], 102 ], [ - ['user_comments', 'user_coments.user'], 3 + ['user_comments', 'user_comments.user'], 3 ] ]; } + + /** + * @dataProvider testWrongRelationNamesDataProvider() + * + * @expectedException \InvalidArgumentException + */ + public function testNestedRelationBadRelationNames($relations) + { + $mapper = test_spot_mapper('\SpotTest\Entity\Post'); + + + $posts = $mapper->all()->with($relations); + foreach ($posts as $post) { + $post->id; + } + } + + public function testWrongRelationNamesDataProvider() + { + return [ + [['user_comments', 'user_commentsss.user']], + [['user_comments.user']], + [['user_comments', 'user_comments.userrr']], + + ]; + } + } From a5793d6e781df3bf8caabe2853554943fcdfbfcb Mon Sep 17 00:00:00 2001 From: alexberezinsky Date: Wed, 26 Jun 2019 10:25:37 +0200 Subject: [PATCH 5/5] Removed the nestedRelation() method from Mapper and from MapperInterface. --- lib/Mapper.php | 17 ++--------------- lib/MapperInterface.php | 10 ---------- tests/NestedRelation.php | 5 +++-- 3 files changed, 5 insertions(+), 27 deletions(-) diff --git a/lib/Mapper.php b/lib/Mapper.php index ac13391..1634a4e 100644 --- a/lib/Mapper.php +++ b/lib/Mapper.php @@ -2,7 +2,7 @@ namespace Spot; use Doctrine\DBAL\Types\Type; -use Spot\Relation\RelationAbstract; +use Spot\Relation\NestedRelation; /** * Base DataMapper @@ -219,19 +219,6 @@ public function belongsTo(EntityInterface $entity, $foreignEntity, $localKey) return new Relation\BelongsTo($this, $foreignEntity, $foreignKey, $localKey, $entity->$localKey); } - /** - * Relation: NestedRelation - * - * @param RelationAbstract $relationObject , - * @param RelationAbstract $parentRelationObject - * - * @return Relation\NestedRelation|bool - */ - public function nestedRelation(RelationAbstract $relationObject, RelationAbstract $parentRelationObject) - { - return new Relation\NestedRelation($relationObject, $parentRelationObject); - } - /** * Prepare entity and load necessary objects on it * @param EntityInterface $entity @@ -489,7 +476,7 @@ protected function with($collection, $entityName, $with = []) throw new \InvalidArgumentException("Nested relation exception: target relation '" . $finalRelationName . "' doesn't exist in Entity '" . $parentRelationEntity . "'"); } $targetRelation = $parentRelationEntity::relations($this, (new $parentRelationEntity))[$finalRelationName]; - $relationObject = $this->nestedRelation($targetRelation, $parentRelation); + $relationObject = new NestedRelation($targetRelation, $parentRelation); } } diff --git a/lib/MapperInterface.php b/lib/MapperInterface.php index 1cff5bf..c14de57 100644 --- a/lib/MapperInterface.php +++ b/lib/MapperInterface.php @@ -94,16 +94,6 @@ public function hasOne(EntityInterface $entity, $foreignEntity, $foreignKey); */ public function belongsTo(EntityInterface $entity, $foreignEntity, $localKey); - /** - * Relation: NestedRelation - * - * Loading multilevel relations - * - * @param RelationAbstract $relationObject , - * @param RelationAbstract $parentRelationObject - */ - public function nestedRelation(RelationAbstract $relationObject, RelationAbstract $parentRelationObject); - /** * Prepare entity and load necessary objects on it */ diff --git a/tests/NestedRelation.php b/tests/NestedRelation.php index c67c603..1e14c7b 100644 --- a/tests/NestedRelation.php +++ b/tests/NestedRelation.php @@ -93,16 +93,18 @@ public function testEagerLoad($relations, $expectedTotalQueries) } $endCount = count($logger->queries); - // Eager-loaded relation should be only 2 queries + // Eager-loaded relation should be only 3 queries $this->assertEquals($startCount+$expectedTotalQueries, $endCount); } public function testEagerLoadDataProvider() { return [ + // without nested relation we will have 102 queries [ ['user_comments'], 102 ], + // with nested relation we will have only 3 queries [ ['user_comments', 'user_comments.user'], 3 ] @@ -131,7 +133,6 @@ public function testWrongRelationNamesDataProvider() [['user_comments', 'user_commentsss.user']], [['user_comments.user']], [['user_comments', 'user_comments.userrr']], - ]; }