Mahmoud Khatib
Mahmoud Khatib

Reputation: 29

laravel : i am trying to get 2 relationships methods in 1 query

what i am trying to do is getting my tvserious and movies from categories class

this is my categories class :

class Category extends Model
{

public function movies()
{
    return $this->hasMany(Movie::class);
}

public function tvserious()
{
    return $this->hasMany(Tvserious::class);
}

what i tried and it's working

public function CategoryClick($slug){



$media = Category::where('slugid',$slug)->with(['movies' => function($query) {
    $query->whereNotNull('title');
},'tvserious' => function($query) {
    $query->whereNotNull('title');
}])->inRandomOrder()->paginate(8);



return view('test')->with([
    'catclick'=>$media,
    'title'=>$slug,
    ]);


}

the problem with this way is in my blade i have to create a loop for movies and tvserious and the tvserious data will always stay at the end at it will show after the movies loop ends

  @foreach($catclick as $media)

         @foreach($media->movies as $movie )                                       

                 {{ $movie->title }}

          @endforeach


          @foreach($media->tvserious as $tvserious )                                       

                 {{ $tvserious->title }}

                 @endforeach

     @endforeach

so how can i get both of my movies and serious in my blade mixed together

i don't want all the movies to be at first so where is the problem and how can i fix this ?

Upvotes: 1

Views: 82

Answers (3)

Mahmoud Khatib
Mahmoud Khatib

Reputation: 29

this worked pretty well for me ... #first

i made an accessor in my category class

  public function getMediaAttribute()
{
    return $this->movies->values()->toBase()
        ->merge($this->tvserious->values())
        ->sortByDesc(function ($media, $key) {
            return $media->updated_at;
        });
}

then in my controller

this is my controller function

use Illuminate\Pagination\LengthAwarePaginator as Paginator;

public function CategoryClick($slug){

$all = Category::where('slugid',$slug)->first()->getMediaAttribute(); // calling the accessor 

// Then use following code to paginate the results:

$perPage = 10;
$currentPage = app('request')->get('page') ?: 1; // or $request->get('page') if available
$paginator = new Paginator($all, $all->count(), $perPage, $currentPage);

return (dd($paginator));

everything is great now thx for everyone who helped me to solve thix issue :D

Upvotes: 1

Namoshek
Namoshek

Reputation: 6544

Add an accessor to your Category model:

class Category
{
    public function getMediaAttribute()
    {
        return $this->movies->values()->toBase()
            ->merge($this->tvserious->values())
            ->sortByDesc(function ($media, $key) {
                return $media->updated_at;
            });
    }
}

Here we used a base collection instead of the Eloquent collection due to merge issues with the Eloquent collection (it does not allow for duplicate keys, thanks @lagbox for pointing it out). After merging both media types together, we also sort the resulting list based on their last update. This means recently touched entries will be listed first.

The newly created list can be accessed with $category->media. Instead of sortByDesc($func) also a simple sortBy('column') or shuffle() (to get a random order) would work.

Upvotes: 0

Davit Zeynalyan
Davit Zeynalyan

Reputation: 8618

You can use this code

@php
    $moviesCount = $media->movies->count();
    $tvseriousCount = $media->tvserious->count();
    $maxCount = ($tvseriousCount > $moviesCount) ? $tvseriousCount : $moviesCount;
@endphp

@for ($index = 0; $index < $maxCount; $index++)

    @isset($media->movies[$index])
        {{ $media->movies[$index]->title }}
    @endisset

    @isset($media->tvserious[$index])
        {{ $media->tvserious[$index]->title }}
    @endisset

@endfor

Upvotes: 0

Related Questions