#Eloquent Multiple Relations

1 messages · Page 1 of 1 (latest)

slender inlet
#

I am pretty new to Laravel and the whole Ecosystem.
I'm trying to Create a little Voting app, where you got Users who can create VoteItems which can be Voted on. So in theory every user should have One Vote for every VoteItem but i can't seem to grasp how i would go about doing that, i got my foreign Keys for user_id and voteItem_id in my migration, but how do i pass those over?

In my Store function i call $request->user()->votes()->create($validated); where the user() part would handle the user_id if i am correct, but how do i get the voteItem_id ?

low moon
# slender inlet I am pretty new to Laravel and the whole Ecosystem. I'm trying to Create a littl...

You would be using route model binding, so your route should include a model key something like /polls/{poll}/vote where {poll} in your URI will be your `voteItem_id in this example.
Then in your store method, you would type hint the model, to pass in the model object.

public function store(VoteRequest $request, Poll $poll)
{
    $poll->votes()->create($request->validated());
}

Obviously this assumes that you have you have a model called poll that you are trying to vote on & that you have a relationship like this on the model:

public function votes()
{
    return $this->hasMany(Vote::class);
}

This also uses the VoteRequest class for validation & authorization, you will probably need to look up Form Requests in the docs.

slender inlet
#

But i got two foreign keys in my Vote Migration

$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->foreignId('voteItem_id')->constrained()->cascadeOnDelete();

so i need both model objects right?

$poll->votes()->create($request->validated());
Would only store the poll and not the user one if i am correct, no?

forest silo
#

Think you can do something like this:

$request->user()->votes()->make($request->validated())->associate($voteItem)->save()
slender inlet
#

This gives me

BadMethodCallException
Call to undefined method App\Models\Vote::associate()```

Do i have to create this?
forest silo
#

Oh.. yeah, my bad, that only works on a relation

#
$vote = $request->user()->votes()->make($request->validated());
$vote->voteItem()->associate($voteItem);
$vote->save();

Then I guess something like this

plucky plank
#

You can't do that

slender inlet
#

Do i have to edit my Vote Model for this?
It gives me this error

Illuminate\Database\Eloquent\Relations\HasOne::associate()```
Because a Vote can only be associated with one VoteItem
My Vote Model Look like this:

class Vote extends Model
{
use HasFactory;

protected $fillable = [
    'voteScore',
];

public function voteItem(): HasOne
{
    return $this->hasOne(VoteItem::class);
}

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

}```

forest silo
plucky plank
#

Relationships don't work with make() as relationships default if the model does not have a primary key

#

You can manually attribute the id in question tho

slender inlet
#

You mean like just pass it as a field in my Array?

plucky plank
slender inlet
#

In my form post request i pass it over as voteItem_id
But when i put that in the "$validated" Array i pass in the
$request->user()->votes()->create($validated);
it gives me a QueryException
SQLSTATE[HY000]: General error: 1 no such table: main.voteItems

#

Ok so look like it needs to be type vote_item_id
But now it gives me an Error of SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: votes.vote_item_id

forest silo
slender inlet
#

Wait, now you got me confused ^^'
User -> hasMany Votes
VoteItem -> hasMany Votes
and
Vote -> hasOne Vote Item AND belongsTo User

forest silo
#

The inverse of hasMany is belongsTo tho

slender inlet
#

so i need to put Vote -> belongsTo Vote Item?

forest silo
#

Yes, a vote item has many votes, a vote belongs to a vote item

slender inlet
#

fixed that, thank you!
As i said im pretty new to Laravel sorry ^^'

But i still dont understand why there is a problem with the vote_item_id
My Schema looks like this

Schema::create('votes', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained()->cascadeOnDelete();
    $table->foreignId('vote_item_id')->constrained()->cascadeOnDelete();
    $table->float('voteScore');
    $table->timestamps();
});
forest silo
#

So what's the error you're seeing now and what are you executing?

slender inlet
#
SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: votes.vote_item_id
INSERT INTO "votes" ("voteScore", "user_id", "updated_at", "created_at") VALUES (11, 1, 2023-07-05 11:29:31, 2023-07-05 11:29:31)```

While i'm excecuting
```$request->user()->votes()->create($validated);```
forest silo
#

Yeah, you'd need to pass the vote_item_id as well. Guess the easiest way is just to do;

$request->user()->votes()->create([
  ...$validated,
  'vote_item_id' => $voteItem->id,
]);

Think my previous solution should work here too, but @plucky plank says it doesn't, so this will do 🙂

slender inlet
#

My Validated Array looks already like this

#
            'voteScore' => 'required|numeric',
            'vote_item_id' => 'required|numeric',
        ]);```
#

So i would assume that the id is also passed

slender inlet
#

Ok looks like the Model wasnt able to fill in that Field.
i changed the fillable and added "vote_item_id" now its working