staudenmeir / eloquent-has-many-deep

Laravel Eloquent HasManyThrough relationships with unlimited levels

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

hasManyDeep with 'where' giving unexpected results

arjendejong12 opened this issue · comments

Hi!

I've got the following relationship: Group -> BelongsToMany -> Post -> HasMany -> Document.
I'm trying to get all documents in a group where the posts have a certain condition (published and not expired).

class Group extends Model
{
    public function posts(): BelongsToMany
    {
        return $this->belongsToMany(Post::class);
    }

    public function documents()
    {
        return $this->hasManyDeep(Document::class, ['group_post', Post::class]);
    }

    public function availableDocuments()
    {
        // I wanted to use the scopes from the Post model here but I'm not sure how and if that is possible, so I've tried it with this.
        return $this->documents()->where(fn ($query) => $query->where('posts.published_at', '>', now())->where('posts.author_id', auth()->user()->id))->orWhere('posts.published_at', '<=', now())
            ->where(fn ($query) => $query->whereNull('posts.expired_at')->orWhere('posts.expired_at', '>', now()));
    }
}
class Post extends Model
{
    public function scopePublished(Builder $query)
    {
        return $query->where(fn ($query) => $query->where('published_at', '>', now())->where('author_id', auth()->user()->id))->orWhere('published_at', '<=', now());
    }

    public function scopeNotExpired(Builder $query)
    {
        return $query->where(fn($query) => $query->whereNull('expired_at')->orWhere('expired_at', '>', now()));
    }

    public function groups(): BelongsToMany
    {
        return $this->belongsToMany(Group::class);
    }

    public function documents(): HasMany
    {
        return $this->hasMany(Document::class);
    }
}
class Document extends Model
{
    public function groups() {
        return $this->hasManyDeepFromRelations($this->post(), (new Post)->groups());
    }

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

The following query returns documents that belong to a post that does not belong to the specific group:

$this->group // Group::find(1); for example
    ->availableDocuments()
    ->with(['post', 'post.author'])
    ->where('documents.type', 'url')
    ->orderBy('created_at', 'desc')
    ->paginate($this->tableRecordsPerPage, ['*'], 'linksPage');

Any idea what I'm doing wrong?

I think I've got it working the way I want it to now. Could you check if this is the way you intended it to work?

class Group extends Model
{
    public function posts(): BelongsToMany
    {
        return $this->belongsToMany(Post::class);
    }

    public function availablePosts(): BelongsToMany
    {
        return $this->posts()->published()->notExpired();
    }

    public function documents()
    {
        return $this->hasManyDeep(Document::class, ['group_post', Post::class]);
    }

    public function availableDocuments()
    {
        return $this->hasManyDeepFromRelationsWithConstraints([$this, 'availablePosts'], [new Post(), 'documents']);
    }
}

Looks good 👍