Link to home
Start Free TrialLog in
Avatar of Eduardo Fuerte
Eduardo FuerteFlag for Brazil

asked on

Could you point a way to enable/ disable an like icon depending on the user had clicked it before or not?

Hi Experts


Could you point a way to enable/ disable an like icon depending on the user had clicked the icon before or not?

Accordingly with:

User generated image
The user has the right of click the "Like" of  a photo once and after that he coudn't do nothing else, the like icon must to be disabled.
If the user reenter the page the like icon for the photo that had received a "like" must to stay disabled, also, by using the user's id.

The actual view:

@extends('layouts.appinterno')

@section('content')

	<div class='row'>

	{{ csrf_field() }}
    <input type="hidden" id="hdnCurtiu" value="{{ $curtiu }}">

        <div class="col-md-12 col-sm-12">
               
                <section class="row">
               
                        @foreach($vitrinesX->chunk(3) as $row)
                        
                            @foreach($row as $vitrine)
                          
                               <div class="col-sm-12 col-md-4">
                               
                                    <div class="box-noticias">
                                       	<a href="javascript:void(0);" onclick='xxx.vitrine.abrirVitrine({{$vitrine->id}});' >
                	    				{{$vitrine->titulo}}
                	    			    </a>                    
                                    </div> 
                                    
                                   	<p id="like" class="likes" onclick="xxx.vitrine.salvarEscolha({{ $vitrine->id }}, 1)">
    				                    <i class="fa fa-thumbs-up"></i> <span id="qtdeCurtiu_{{ $vitrine->id }}">{{ $vitrine->qtdeCurtiu }}</span>
    				               	</p> 
                     
                               </div>     
                              
                            @endforeach
                            
                        @endforeach
                          
                                                  
                </section>
			</div>

	</div>
@endsection


@section('scripts')

	<script src="{{ asset('js/xxx/xxx.Formatadores.js').'?v='xxx(uniqid()) }}" ></script>
	<script src="{{ asset('js/xxx/xxx.Vitrine.js').'?v='xxx(uniqid()) }}" ></script>

	<script>
		$(document).ready(function() {
			if($('#hdnCurtiu').val() == "1")
				$('#like').addClass('like');
			else if($('#hdnCurtiu').val() == "0")
				$('#dislike').addClass('like');
		})
	</script>

@endsection

Open in new window


I guess when the page starts it must to be checked on the existent jQuery code

JS code for the view (where I guess it must to be checked):

Vitrine.prototype.abrirVitrine = function(id) {
  $.ajax({
    url: "/vitrine/" + id + "/obter",
    method: "GET",
    error: function() {
      xxx.openModalCustom(
        "Erro",
        "Erro ao obter a notícia.",
        "Entendi",
        "error"
      );
    },
    success: function(data) {
      datacriacao = xxx.formatadores.DataBDParaDataBrasil(
        data.retorno.created_at
      );
      titulo = data.retorno.titulo;
      subtitulo = data.retorno.subtitulo;
      conteudo = data.retorno.conteudo;
      url = data.retorno.url;
      $("#datacriacao").html(datacriacao);
      $("#titulo").html(titulo);
      $("#subtitulo").html(subtitulo);
      $("#conteudo").html(conteudo);
      $("#image").attr("src", url);
      $("html, body").animate(
        { scrollTop: $("#datacriacao").offset().top },
        1000
      );
    }
  });
};

Open in new window



Controller code (where the above JS calls the obter method):
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;

use Debugbar;
use DB;

class UserVitrine extends Model
{
    public function obter($user_id, $vitrine_id){
    
        return UserVitrine
            ::where('user_id', \DB::raw($user_id))
            ->where('vitrine_id', \DB::raw($vitrine_id))
            ->first();
    }
    
    public function obterCurtidasPorVitrine($vitrine_id, $curtiu){

        return UserVitrine
            ::where('vitrine_id', \DB::raw($vitrine_id))
            ->where('curtiu', \DB::raw($curtiu))
            ->count();
            
    }		
    
 		
}

Open in new window


Thanks in advance!
Avatar of lenamtl
lenamtl
Flag of Canada image

Hi,

I guess you want to disable the button not only the icon?

So you can add the disabled to the button
here is an example with the Bootstrap class
<button type="button" class="btn btn-lg btn-primary" disabled>Primary button</button>

Open in new window


You will need some server side to apply the class based on your requirements and a way to remember the state.
You can save the state to DB (this will kept the value for that user even if he clear the browser cache)

or you can use localstorage or sessionstorage but the user can clear the cache and the saved value will be lost.
https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage

**Remember that this can be easily edited from browser console so you may want to have server side validation to make sure.
Hey Eduardo,

Based on previous conversations we've had ... remember that your Vitrines has a many-to-many relationship with the Users where you record the Likes and Dislikes.

Using that, you should be able to attach a list of Users to each Vitrine. Then you can check that list against the current User and if they exist in the list, then you know they've Liked or Disliked the Vitrine before, so you can set the buttons to disabled.
Avatar of Eduardo Fuerte

ASKER

Hi Chris

Hard to me how to implement that...

1. Something like that at VitrinesController
 
// Previous data (last question)
           $vitrinesX = Vitrine
                ::vigente()
                ->ativa()
                ->aprovada()
                ->global(Auth::user()->tipoparticipante_id)
                ->orderBy('id','desc')
                 ->withCount([
                        'user_vitrines as qtdeCurtiu' => function (Builder $query) { $query->where('curtiu', 1); },
                        //'user_vitrines as dislikes' => function (Builder $query) { $query->where('curtiu', 0); }
                    ])
                    ->get();

// The new Collection to be send to the view:  Needed columns vitrine_id and user_id 

$data = Vitrine::with('user_vitrines')->get();

dd($data);  // Difficult to obtain informations here
  

Open in new window



Could you check?
Hey Eduardo,

There are a couple of ways you can do this. Probably the easiest way is to atatch a list of UserIds to each Image. To do this, I'll assume you have your many-to-many realtionshps set up correctly.

I'll give you a quick example, but I'll need to use English - hope you can follow that. Let's assume we have 2 models - User & Image. The 2 models will have a many-to-many realtionship (an image can be voted on by many users // a user can vote on many images), so we'll have a pivot table to link the 2. On that pivot table, we'll store the extra info a vote column (used to indicate a Like or Dislike). The basics of this means that we end up with 3 tables in the DB, for example:

users
    id
    name

images
    id
    title
    filename

image_user
    id
    user_id
    image_id
    vote

Open in new window

We set up the relationships at the Model level where we can tell Laravel to include the Vote data from the pivot table.

class User {
    public function images() {
        return $this->belongsToMany(Image::class)->withPivot('vote');
    }
}

class Image {
    public function users() {
        return $this->belongsToMany(User::class)->withPivot('vote');
    }
}

Open in new window

This now means that for each User we can access the Images they've voted on - $user->images(); and for each Image, we can access the Users who have voted on it - $image->users();

Now, in your controller, the trick is to retreive the list of IDs for the Users that have voted on an Image and attach that to each image. Take a look at this:

$images = Image::with('members')->get()
    ->each(function($image) {
        $image->votedBy = $image->members->pluck('id');
    });

Open in new window

What we're doing here is loading all images from the database, along with the related members. We're then looping over each image and setting a new property called votedBy. The value of this new property is a collection of Member IDs. Now for each image in our collection, we end up with something like this:

$image->title = "Image 1"
$image->filename = "image1.jpg"
$image->votedBy = [1, 5, 7, 10, 13] <-- This shows the IDs of Users who have voted on this image.

You then pass that data ($images) into your View:

return view('yourview', compact($images));

And then loop through your $images collection to output the info. During the loop, you check to see if a given user ID exists in the votedBy collection and act accordingly:

@foreach ($images as $image)
    @php $hasUserVoted = $image->votedBy->contains($userId); @endphp
    <div>
        <h2>{{ $image->title }}</h2>
        <button {{ $hasUserVoted ? 'disabled' : '' }}>Like</button> <button {{ $hasUserVoted ? 'disabled' : '' }}>Dislike</button>
    </div>
@endforeach

Open in new window

All we're doing here is checking whether the votedBy collection contains a given userId, and setting a variable to either true or false. We then use that variable to decide whether to echo 'disabled' into the button or not.

Hope that all makes sense :)
Hi Chris

Thank you for so elaborated reply.

Trying to correct correlate your code to what I have here (equivalent to the last question)


User generated image

On the User Model I coded:

public function vitrines() {
	return $this->belongsToMany(Vitrines::class)->withPivot('user_vitrines');
} 
//------------------------------
//Correspondent to your code
//-----------------------------
class User {
    public function images() {
        return $this->belongsToMany(Image::class)->withPivot('vote');
    }
}

Open in new window


On the Vitrine Model I coded:

public function users() {
	return $this->belongsToMany(User::class)->withPivot('user_vitrines');
}

//------------------------------
//Correspondent to your code
//-----------------------------
class Image {
    public function users() {
        return $this->belongsToMany(User::class)->withPivot('vote');
    }

Open in new window


On the UserVitrine Model I didn't code.

At VitrinesController (where on the last question the information "curtiu" is obtained)

//--------------------
// Code last question
//--------------------
$vitrinesX = Vitrine
	::vigente()
	->ativa()
	->aprovada()
	->global([0])
	->orderBy('id','desc')
	 ->withCount([
			'user_vitrines as qtdeCurtiu' => function (Builder $query) { $query->where('curtiu', 1); },
			//'user_vitrines as dislikes' => function (Builder $query) { $query->where('curtiu', 0); }
		])
		->get();

//-------------
// Added now
//-------------
$images = Vitrine::with('users')->get()
->each(function($vitrine) {
	$image->curtiu= $image->users->pluck('id');
});

//---------------------------------------
//  Correspondent to your code
//---------------------------------------
$images = Image::with('members')->get()
    ->each(function($image) {
        $image->votedBy = $image->members->pluck('id');
    });
//-------------------------------------------------------------------------------

// This returns to Vitrine view
return view('vitrines.index',compact('vitrinesX', 'images', 'vitrine','qtdeCurtiu','qtdeNaoCurtiu','curtiu'));

Open in new window



I'm certainly misconcepting something since this error arises:
User generated image
Could you check?
Hi Eduardo,

Couple of issue with your code. When we call withPivot, we need to specify the column name from the Pivot table, so in your case, that's 'curtiu', so:

//User Model
public function vitrines() {
    return $this->belongsToMany(Vitrines::class)->withPivot('curtiu');
} 

//Vitrine Model
public function users() {
    return $this->belongsToMany(User::class)->withPivot('curtiu');
}

Open in new window

Adjusted

This code must to be adapted also:
User generated image
// line 97
    $images = Vitrine::with('users')->get()
        ->each(function($vitrine) {
            $image->curtiu = $image->users->pluck('id');
        });
     

Open in new window


Since this error occurs:
Hey Eduardo,

Inside your closure, you're passing in a variable called $vitrine, but then you're trying to use a variable called $image. Change that to $vitrine

$vitrine->curtui = $vitrine->users->pluck('id');
Hi  Chris

So did I:

        $images = Vitrine::with('users')->get()
        ->each(function($vitrine) {
            $vitrine->curtiu = $vitrine->users->pluck('id');
        });

Open in new window


But the SQL error table not found remains ...

The model UserVitrines doesn't received any method... isn't it necessary?
Hey Eduardo,

It looks like you've named your SQL table incorrectly. Normally, when we create a many-to-many relationship. Laravel expects the pivot table to be named model_model (singular not plural). It also expects this table to be named from the 2 models it links in alphabetical order, so in your case you have 2 models - User and Vitrine. The pivot table to link these 2 together should be called user_vitrine. In your schema diagram, it looks like it's called user_vitrines (with an s on the end), which is why Laravel can't find it.

You also mention having a UserVitrines model. How dod you create that Model, because normally, if you want to use a Custom Pivot class, you need to extend the Pivot class (not the Model) and make sure you're relationship are using that.
If you really don't want to use the standard names for your pivot table (I would suggest you do), then you can pass a second argument to the belongsToMany() method:

public function vitrines() {
    return $this->belongsToMany(Vitrines::class, 'user_vitrines')->withPivot('curtiu');
}
Going the 1st way, renaming to user_vitrine:


// That start runs      
$images = Vitrine::with('users')->get()
->each(function($vitrine) {
	$vitrine->curtiu = $vitrine->users->pluck('id');
});

//Obtains data
dd($images)

Open in new window



// But this that was OK starts with error      

$vitrinesX = Vitrine
::vigente()
->ativa()
->aprovada()
->global(Auth::user()->tipoparticipante_id)
->orderBy('id','desc')
 ->withCount([
		'user_vitrines as qtdeCurtiu' => function (Builder $query) { $query->where('curtiu', 1); },
		'user_vitrines as dislikes' => function (Builder $query) { $query->where('curtiu', 0); }
	])
	->get();

Open in new window


So I guess something must to be adjusted on the Models to adapt it to the to the new table name, isn't it?


Going the 2nd way:

Returning back to the previous table name:
rename table user_vitrine to user_vitrines

Open in new window



Adjusted on the model User
   public function vitrines() {
    return $this->belongsToMany(Vitrines::class, 'user_vitrines')->withPivot('curtiu');
}   

Open in new window


The 02 Controller codes started going with error....

And I saw that renaming the table to user_vitrine brokes another parts of the code  - on the Model UserVitrine, really intricated....


If necessary the Models code just sinalize, please.
OK.

Let's take a step back a see if we can figure out what's going on. You should have 2 models - User and Vitrine. These 2 models have database tables called users and vitrines. You also have a 3rd table called user_vitrine - this is the pivot table to link the many-to-many relationship between User and Vitrine (no need for a Model at this point). That table has fields called user_id and vitrine_id, plus an additional column called curtiu.

On your User model, you define the relationship to the many Vitrine objects like so:

public function vitrines() {
    return $this->belongsToMany(Vitrine::class)->withPivot('curtiu');
}

Open in new window

And on the Vitrine model, you define the inverse relationship like so:

public function users() {
    return $this->belongsToMany(User::class)->withPivot('curtiu');
}

Open in new window


That's the basics of setting up a many-to-many relationship. That's all you need for that to work.

Now in your controller, when you want to see which users have liked (or disliked) an image, you can do the following:

$images = Vitrine::with('users')->get()
    ->each(function($vitrine) {
        $vitrine->curtiu = $vitrine->users->pluck('id');
    });

Open in new window

That will retrieve a list of Images ($images). Each Image will have a property called curtiu that contains a collection of UserId (Users that have liked an image).

If you want to get a count of the likes and dislikes, then you can call withCount against the Relationship property (users on Vitrine), so something like this:

$images = Vitrine::with('users')
    ->withCount([
        'users as likes' => function (Builder $query) { $query->where('curtiu', 1); },
        'users as dislikes' => function (Builder $query) { $query->where('curtiu', 0); }
    ])
    ->get();

Open in new window

That will retrieve a list of Images ($images). Each image will have 2 new properties called likes and dislikes that contain the number of likes ('curtiu' = 1) and dislikes ('curtiu' = 1) from the pivot table.

You can now string those 2 things together in your controller, so something like this:

$images = Vitrine::with('users')
    ->withCount([
        'users as likes' => function (Builder $query) { $query->where('curtiu', 1); },
        'users as dislikes' => function (Builder $query) { $query->where('curtiu', 0); }
    ])
    ->get()
    ->each(function($vitrine) {
        $vitrine->curtiu = $vitrine->users->pluck('id');
    });

Open in new window

That will retreive a list of Images ($images). Each image will have 3 extra properties - likes (containing the number of likes), dislikes (containing the number of dislikes) and curtiu (containing a list of UserIds that have liked or disliked the image).
I'm going to check all the points above.

But just one thing I did that eliminated the errors:

Maintained as before:

User Model
   public function vitrines() {
        return $this->belongsToMany(Vitrines::class)->withPivot('curtiu');
    }

Open in new window


Vitrine Model  Adjusted to:
    public function users() {
        //return $this->belongsToMany(User::class)->withPivot('curtiu');
        return $this->belongsToMany(User::class, 'user_vitrines')->withPivot('curtiu');    
    }

Open in new window



Controller code:

           $vitrinesX = Vitrine
                ::vigente()
                ->ativa()
                ->aprovada()
                ->global(Auth::user()->tipoparticipante_id)
                ->orderBy('id','desc')
                 ->withCount([

//--- changed to user_vitrine  (from users_vitrine)
                        'user_vitrine as qtdeCurtiu' => function (Builder $query) { $query->where('curtiu', 1); },
                        //'user_vitrines as dislikes' => function (Builder $query) { $query->where('curtiu', 0); }
                    ])
                    ->get();
                    
                    
                    
                // EF 2020
                $images = Vitrine::with('users')->get()
                ->each(function($vitrine) {
                    $vitrine->curtiu = $vitrine->users->pluck('id');
                });

Open in new window



Opening the view $images is presented with dd

Does it makes any sense?
Hey Eduardo,

In your User model you have this:

public function vitrines() {
    return $this->belongsToMany(Vitrines::class)->withPivot('curtiu');
}

I thought your model was called Vitrine (no s).

In this line: 'user_vitrine as qtdeCurtiu' => function (Builder $query)

user_vitrine refers to the name of your Relationship method on your Vitrine class. In my example above, I just called it users():

public function users() {
    return $this->belongsToMany(User::class)->withPivot('curtiu');
}

It's up to you what you call it, but make sure that whatever you do call it, you use in the controller.

It now sounds like you might have 2 different methods on your Vitrine model - one called users() and one called user_vitrine(). Are they not doing the same thing - getting the related User models?
Hi Chris


I thought your model was called Vitrine (no s).
=> Yes


In your User model you have this:

public function vitrines() {
    return $this->belongsToMany(Vitrines::class)->withPivot('curtiu');
}

=> Yes
OK, so this is wrong:

public function vitrines() {
    return $this->belongsToMany(Vitrines::class)->withPivot('curtiu');
}

You shouldnt add the s to Vitrines::class, It should be:

public function vitrines() {
    return $this->belongsToMany(Vitrine::class)->withPivot('curtiu');
}
Vitrine Model

    //public function user_vitrines() {

 // Used before at the last question... (and stays)
    public function user_vitrine() {
        return $this->hasMany('App\Models\UserVitrine');
    }
    
    public function users() {
        //return $this->belongsToMany(User::class)->withPivot('curtiu');
        return $this->belongsToMany(User::class, 'user_vitrines')->withPivot('curtiu');    
    }

Open in new window

Chris


Could you check my code?

Hard to follow what's the correct version...
Hmmm. Maybe I'm missing something as I'm a little confused about your Relationships.

Is this correct. You have Users on your system and you have Vitrines on your system. A user can like many Vitrines, and a Vitrine can be liked by many Users?

If that is correct, then that's a many-to-many relationship, linked by a pivot table and modeled by the belongsToMany() methods.

What is the UserVitrine model used for? As you have it, each single Vitrine can have many UserVitrines, but I don't understand what that model is for.
It's my understanding that you should have 2 models (User / Vitrine). These 2 models each have their own db table (users / vitrines). There is also a 3rd table called user_vitrine which links to 2 tables together (called a pivot table), but there is no need for a 3rd model called UserVitrine. Your User model links to the many Vitrine models by using the belongsToMany() method and your Vitrine model links to the many User models by using the belongsToMany() method.
Users (Authenticatable)

<?php

namespace App;

use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

use App\Notifications\RedefinirSenha;

class User extends Authenticatable
{
    use HasApiTokens,Notifiable;

}

Open in new window

The model actualized:

User generated image
The correct pages names:

User generated image
SOLUTION
Avatar of Chris Stanyon
Chris Stanyon
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Sorry

I had to reconsider UserVitrine, because the VitrinesController is calling it:


    $mUserVitrine = new UserVitrine();
        $qtdeCurtiu = 0;
        $qtdeNaoCurtiu = 0;
        
        $userVitrine = null;
      
        if(!empty($vitrine)){
          $qtdeCurtiu = $mUserVitrine->obterCurtidasPorVitrine($vitrine->id, 1);
          $qtdeNaoCurtiu = $mUserVitrine->obterCurtidasPorVitrine($vitrine->id, 0);

          $userVitrine = $mUserVitrine->obter(Auth::user()->id, $vitrine->id);
        } else {
          $qtdeCurtiu = $mUserVitrine->obterCurtidasPorVitrine($vitrinesX[0]->id, 1);
          $qtdeNaoCurtiu = $mUserVitrine->obterCurtidasPorVitrine($vitrinesX[0]->id, 0);

          $userVitrine = $mUserVitrine->obter(Auth::user()->id, $vitrinesX[0]->id);
        }
        $curtiu = !empty($userVitrine) ? $userVitrine->curtiu : "";
        
        
   
       
        //return view('vitrines.index',compact('vitrinesX','vitrine','qtdeCurtiu','qtdeNaoCurtiu','curtiu'));
        
        return view('vitrines.index',compact('vitrinesX', 'images', 'vitrine','qtdeCurtiu','qtdeNaoCurtiu','curtiu'));
    }

Open in new window

And when called this error arises:
 User generated image
And when saving a like

VitrinesController

  public function salvarEscolha(Request $request){

      $vitrine_id = $request->input('vitrine_id');
      $curtiu = $request->input('curtiu');

info($vitrine_id);
info($curtiu);

      $mUserVitrine = new UserVitrine();
   
      $userVitrine = $mUserVitrine->obter(Auth::user()->id, $vitrine_id);


      if(empty($userVitrine)){
        $userVitrine = new UserVitrine();
        $userVitrine->user_id = Auth::user()->id;
        $userVitrine->vitrine_id = $vitrine_id;
        $userVitrine->created_at = Carbon::now();
      }

      $userVitrine->curtiu = $curtiu;
      $userVitrine->updated_at = Carbon::now();
      $userVitrine->save();

      return response()->json(new Resultado(true, 'Sucesso', null), 200);
    }

Open in new window


A similar error occurs since the table user_vitrines isn't found.
User generated image
Chris


This part could be easily eliminated since it was part of an old code:

//        $mUserVitrine = new UserVitrine();
//        $qtdeCurtiu = 0;
//        $qtdeNaoCurtiu = 0;
//        
//        $userVitrine = null;
//      
//        if(!empty($vitrine)){
//          $qtdeCurtiu = $mUserVitrine->obterCurtidasPorVitrine($vitrine->id, 1);
//          $qtdeNaoCurtiu = $mUserVitrine->obterCurtidasPorVitrine($vitrine->id, 0);
//
//          $userVitrine = $mUserVitrine->obter(Auth::user()->id, $vitrine->id);
//        } else {
//          $qtdeCurtiu = $mUserVitrine->obterCurtidasPorVitrine($vitrinesX[0]->id, 1);
//          $qtdeNaoCurtiu = $mUserVitrine->obterCurtidasPorVitrine($vitrinesX[0]->id, 0);
//
//          $userVitrine = $mUserVitrine->obter(Auth::user()->id, $vitrinesX[0]->id);
//        }
//        $curtiu = !empty($userVitrine) ? $userVitrine->curtiu : "";
        
// Just maintaining it for view's compatibility:
        $curtiu = 0;

Open in new window




But on the method  salvarEscolha above the data must to be saved at the table user_vitrine - I don't know how to change it, since it still looking for the table user_vitrines.
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Chris

So did I

    public function salvarEscolha(Request $request) {
    
        $vitrine_id = $request->vitrine_id;
        $curtiu = $request->curtiu;
        
        info('xxx');
        info($vitrine_id);
        info($curtiu);
        
    
        Auth::user()->vitrines()->sync(array($vitrine_id => array('curtiu' => $curtiu)), false);
    
        return response()->json(new Resultado(true, 'Sucesso', null), 200);
    }

Open in new window


With this error:

User generated image
It is is due:
App\Models\Vitrine.php
    public function vitrines() {
        return $this->belongsToMany(Models\Vitrine::class)->withPivot('curtiu');
    } 

Open in new window


No error...

And data created at DB:

select * from user_vitrine order by id desc

Open in new window


User generated image
Chris


It looks everything is fine....what a fight!
Chris

Thank you very much for another outstanding (hard and didactic) solution!!!
Since this question assumed  a high degree of difficulty,  I'm going to open another question for the 2nd part.
Hey Eduardo,

Glad we got there in the end. I think the problems with this question were largely down to how you were managing your Relationships. Once the Models and relationships (along with the DB tables) were in place correctly, it all started to make more sense.
I agree with you.
Laravel Eloquent demands time and efforts to know its tricks.
It's not always intuitive. A lot of details you informed demands a lot of experience, no easily one with little experience could go to solve it in low time.