Skip to content

Conversation

@alexberezinsky
Copy link

NestedRelation can be used for eager-loading of multi-level related entities.

Usage example for Post Entity:

namespace Entity;

use Spot\EntityInterface as Entity;
use Spot\MapperInterface as Mapper;

class Post extends \Spot\Entity
{
    protected static $table = 'posts';

    public static function fields()
    {
        return [
            'id'           => ['type' => 'integer', 'autoincrement' => true, 'primary' => true],
            'user_id'      => ['type' => 'integer', 'required' => true],
            'title'        => ['type' => 'string', 'required' => true],
            'body'         => ['type' => 'text', 'required' => true],
            'status'       => ['type' => 'integer', 'default' => 0, 'index' => true],
            'date_created' => ['type' => 'datetime', 'value' => new \DateTime()]
        ];
    }

    public static function relations(Mapper $mapper, Entity $entity)
    {
        $userRelation = $mapper->belongsTo($entity, 'Entity\User', 'user_id');
        $profileRelation =  User::relations($mapper, $entity)['profile'];
        return [
            'user' => $userRelation,
            'user.profile' => $mapper->nestedRelation($profileRelation, $userRelation);
        ];
    }
}

And then we can eager load user profiles with posts:

$posts = $posts->all()->with(['user', 'user.profile']);

NestedRelation can be used with any relations and can be multilevel. For example:

$posts = $posts->all()->with([
     'user', 
     'user.profile'
     'user.profile.image',
     'comments',
     'comments.user',
     'comments.user.profile',
     'comments.user.profile.image'
]);

@alexberezinsky
Copy link
Author

Hey guys. Please tell me what do you think about this idea. I use it for one of my projects to avoid lazy-loading of related entities. This can save a lot of db queries. I would like to contribute it to Spot2.
If you like the idea I can continue working on it and improve it further.

@FlipEverything
Copy link
Contributor

I like it! Somebody from the team will review it as soon as possible.

@alexberezinsky
Copy link
Author

Ok, great. Thanks.

@alexberezinsky
Copy link
Author

Hey guys,

I added some tests to the new relation.

Also I changed the way of adding nested relations to entities. So actually now there is no need to define them inside entities. Nested relations will be created automatically when added with 'with' method. So the only things to ensure is that all the parent levels are loaded and the target relation exists. For example:

$posts->all()->with(['user_comments', 'user_comments.user']);

For this case Post entity should have a 'user_comments' relation and UserComment entity should have 'user' relation. That will be enough for the above code to work.

I can improve it further if there is a need.

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants