staudenmeir / eloquent-has-many-deep

Laravel Eloquent HasManyThrough relationships with unlimited levels
MIT License
2.67k stars 157 forks source link

Help with grouping #103

Closed SuryaVanLierde closed 3 years ago

SuryaVanLierde commented 4 years ago

Models and relations

class Publisher extends Model
{
    use HasRelationships;

    public function collections(): BelongsToMany
    {
        return $this->belongsToMany(Collection::class)
            ->orderBy('title')
            ->using(CollectionPublisher::class);
    }

    public function series(): HasManyDeep
    {
        return $this->hasManyDeepFromRelations($this->collections(), (new Collection())->series());
    }
}
class Collection extends Model
{
    use HasRelationships, Translatable;

    public function editions(): HasMany
    {
        return $this->hasMany(Edition::class);
    }

    public function series(): HasManyDeep
    {
        return $this->hasManyDeepFromRelations($this->editions(), (new Edition)->series());
    }
}
class Edition extends Model
{
    use HasRelationships, LoadsRelationshipsWithoutScopes, Translatable;

    public function series(): BelongsTo
    {
        return $this->belongsTo(Series::class);
    }

    public function collection(): BelongsTo
    {
        return $this->belongsTo(Collection::class);
    }
}

And of course there is a Series model.


The problem is that the series relation on the Publisher is returning each Series as many times as there is an Edition for that Publisher in the Series

How do I trim it down so each series is only returned once?

A simple groupBy('series.id') does not work due to the full group by limitations, and I'm not sure how to get around this using the has many deep package.

staudenmeir commented 4 years ago

How are you using the relationship in your query?

SuryaVanLierde commented 4 years ago

Thanks for the quick response

Pretty basic really

$series = $publisher->series();

where $publisher ins an instance of Publisher received from the request

staudenmeir commented 4 years ago

Please try this:

$publisher->series()->toBase()->select('series.*')->groupBy('series.id')->get();
SuryaVanLierde commented 4 years ago

That works, to some extent. It means I now get all the records I want, but as stdClass, not as model instances, which means the eager loaded translations are no longer part of the result set. Any way of writing this and still getting the model instances? The main problem here is that the Series need to be sorted by title, but the title is a relation as some series are available in multiple languages.

class Series extends Model
{
    use HasRelationships;

    protected $appends = [
        'title_display',
    ];

I also plan on using paginate() on the query

staudenmeir commented 4 years ago

I actually wanted to suggest this query:

$publisher->series()->getQuery()->select('series.*')->groupBy('series.id')->get();

groupBy() works with pagination:

$publisher->series()->groupBy('series.id')->paginate();
SuryaVanLierde commented 4 years ago

Perfect. Thanks so much for your help given that my problem was not strictly with your package.

I just wish some of these functions you are using like getQuery and toBase would be documented, as they clearly are useful.