Realtionships that require an authenticated User

Published 4 months ago by JayBird

Say you have a User Model.

You also have a Products Model.

Users can create private notes about products.

When getting all the products, I want to eager load the notes for each product for the currently authenticated user.

I am currently doing it like this...

public function notes()
{
    if (! auth()->check()) {
        throw new \Exception('You cannot use the '.__METHOD__.' relationship when there is no authenticated user.');
    }

    return $this->hasOne(Notes::class, 'product_id', 'product_id')->where('userID', auth()->user()->userID);
}

It works fine, but seems a little messy.

Is there a better way?

Thanks

shez1983

indeed it is.. what is wrong with normal relationship that Laravel docs tell you about?

just do a return $this->hasOne(Note::class, fk, pk);

and for authenticated user just do

\Auth::user()->notes
JayBird

Okay, so how would you display a list of products, and below each product, show the currently authenticated users note (if any) with the relevant product?

There is no relationship between the User and the Product

Swaz
Swaz
4 months ago (56,575 XP)

You could probably do something like this:

$products = Product::with(['notes' => function ($query) {
    $query->where('user_id', auth()->id);
}]);
class Product
{
    public function notes()
    {
        return $this->hasMany(Note::class)
    }
}

The notes table would have these columns:

id | user_id | product_id | note
Snapey
Snapey
4 months ago (897,275 XP)
biishmar

Do the normal relationship .. in the view do this

@auth

$user->product->note

@endauth
austenc

So what happens if no user is logged in, do you want all products' notes?

If you're not worried about that, this should get you what you want:

    $query = $this->hasOne(Notes::class, 'product_id', 'product_id');

    if (auth()->check()) {
        $query->where('userID', auth()->id());
    }

    return $query;

shez1983

i dont agree with the above post..

@JayBird

There is no relationship between the User and the Product

There is no direct relationship but assuming its an ecommerce site there is an indirect relationship through orders....

until you tell me you db schema i m not able to give a definite reply but my answer would be similar to one posted by swaz

Snapey
Snapey
3 months ago (897,275 XP)

my earlier comment seems to have just gone over the heads

A note belongs to a Product - yes? A note belongs to a User - yes ?

If not then you cannot do what you want.

when loading products you would do something like

$products = Product::with('notes')->get();

but this will load all notes. Not what was wanted.

so scope the model or limit the with(), eg

$products = Product::with(['notes' => function($query){
    $query-where('user_id', request()->user()->id);
    }])->get();

or with a global scope in the Note model

protected static function boot()
{
    parent::boot();

    static::addGlobalScope('usernote', function (Builder $builder) {
        $builder->where('user_id', request()->user()->id);
    });
}
shez1983

@Snapey no it didnt - because @Swaz answer was the same as yours!!! which i referred to.

Snapey
Snapey
3 months ago (897,275 XP)

@shez noone else mentioned scopes, and your answer completely missed the point (which was to show the users notes related to the products being viewed)

and relationship through orders... who mentioned orders?

shez1983

oh give me a break - scopes or not.. your query is the same as swaz.. scopes is just a nice additional thing to use as an added bonus.... even without it your/swaz's other query would work fine..

he might not even need scope if he is doing it in one place..

you dont need to mention orders.. i was making an assumption and stated as such (so could be wrong) but.. USER and PRODUCT.. hello.. any one might/would associate those two with an ecommerce system unless OP Is a millionnaire giving away products for free

Please sign in or create an account to participate in this conversation.