Search code examples
phpmysqllaravelunionmodels

Laravel union within model functions


Hello i am new here and not a native English speaker so please forgive me for any mistakes on my grammar and on my question formatting.

I am building an app with php using laravel framework 5.4 version. The web app is very simple its for reviewing articles and users that posts articles.

I would like to learn how i can union the results of the functions within my model. I want the allReviews function from user model to return the reviews the user has mixed with the reviews his articles have orderby createdtime.

let me explain better.

here is my 3 main tables:

Users     | Articles  | Reviews
--------- | --------- | --------- 
id        | id        | id
name      | user_id   | reviewable_id
email     | title     | reviewable_type
password  | body      | reviewtext
etc..     | etc..     | created_time

and here is my models code :

class User extends Model{

    protected $table = 'users';

    public function articles()
    {
        return $this->hasMany(Article::class,'user_id');
    }

    public function reviews(){
        return $this->morphMany(Review::class,'reviewable');
    }

    public function allReviews(){
        /*
         i want union something like this:

        $result = $this->reviews() union
        foreach ($this->Articles() as $Article) {
            union $Article->reviews();
        }
        orderby created_time ASC or DESC doesn't matter

        return $result
        */
    }
}

class Article extends Model{

    protected $table = 'articles';

    public function user()
    {
        return $this->belongsTo(User::class,'user_id');
    }

    public function reviews(){
        return $this->morphMany(Review::class,'reviewable');
    }
}

class Review extends Model{

    protected $table = 'reviews';

    public function reviewable(){
        return $this->morphTo('reviewable');
    }
}

So my question is how i can do the function allReviews from user to work ?

Any help is appreciated :) Thank You


Solution

  • Calling the $user->reviews property will return all reviewable models. You don't have to UNION anything, Eloquent will take care of that for you.

    Try this:

    public function allReviews(){
        $reviews = new \Illuminate\Database\Eloquent\Collection;
    
        foreach($this->articles as $article)
        {
            $reviews = $reviews->merge($article->reviews);
        }
    
        $reviews = $reviews->merge($this->reviews);
    
        return $reviews;
    }
    

    I'm really tired now and I have a feeling you might get the N+1 query problem situation here but it should work for you.