Joining the hasOne model to another Laravel / Eloquent model without specifying an identifier

Background

Given that we have the following two tables, where type_id refers to the specified Type string:

Question

id | type_id | description ---+---------+------------ 1 | 1 | A nice question .. | .. | .. 

questionType

 id | name ---+---------------- 1 | Multiple-choice .. | .. 

with the following worm models:

 class Question extends Model { public function type() { return $this->hasOne( 'QuestionType', 'id', 'type_id' ); } } class QuestionType extends Model { } 

Question 1

How to add a new question that refers to an existing question type without manual action with identifiers? For example, the following works, but is ugly imo, since I have to manually assign the appropriate question type identifier:

 $q = new Question; $q->type_id = 1; // Multiple-choice $q->description = 'This is a multiple-choice question'; $q->save(); 

One would think that there is a way to allow ORM to handle id assignments (shouldn't things be avoided with ORM?), Something like this (this does not work in Eloquent ORM):

 $q = new Question; $q->type = QuestionType.where('name', '=', 'Multiple-choice'); $q->description = 'This is a multiple-choice question'; $q->save(); 

Question 2

In relation to question 1, how can I add a new question that refers to a new type of question, without manual action with identifiers? In the same way, I imagine something like:

 $t = new QuestionType; $t->name = 'Another type'; $q = new Question; $q->type = $t; $q->description = 'This is a multiple-choice question'; $q->save(); 

Here I would like $q->save() to save both the new question type and the question (or something similar).

The following steps, but again, I assign the identifier itself, which, in my opinion, should handle the ORM:

 $t = new QuestionType; $t->name = 'Another type'; $t->save(); $q = new Question; $q->type = $t->id; $q->description = 'This is a multiple-choice question'; $q->save(); 

I tried playing with various combinations of save() , update() methods with no luck. I also searched for attach() , which exists in the hasMany relationship but seems to be missing in hasOne .

+6
source share
2 answers

First, you misunderstood the attitude you are referring to.

Here is what you need:

 // Question model public function questionType() { return $this->belongsTo('QuestionType', 'type_id'); } // QuestionType model public function questions() { return $this->hasMany('Question', 'type_id'); } 

then you can link them as follows:

 $questionType = QuestionType::where(..)->first(); $question = new Question; ... // do something with it // associate $question->questionType()->associate($questionType); // or the other way around - save new question and link to the type: $questionType->questions()->save($question); 

You can explicitly pass an identifier for communication:

 $question->type_id = $someTypeId; $question->save(); 

You cannot do this:

 $question->questionType = $someQuestionType; 

for this way. Eloquent handles model attributes, not relationships.


Question 2 :

 $questionType = new QuestionType(['name' => 'multiple']); $questionType->save(); $question = new Question([ ... some values ... ]); // then either this way: $questionType->questions()->save($question); // or, again, the other way around: $question->questionType()->associate($questionType); $question->save(); 
+10
source

Answering question 1, both methods are good for me, you do not need to change anything.

In answer to question 2, you must do this, as you have shown. ORM will not be automatically created by QuestionType until you use the save method manually.

For example, if you used the code:

 $t = new QuestionType; $t->name = 'Another type'; $t2 = new QuestionType; $t2->name = 'Another type 2'; $q = new Question; $q->type = $t; // what here - $t2 or $t ? $q->description = 'This is a multiple-choice question'; $q->save(); 

What should ORM decide? The question is not related to any of $t or $t2 , so ORM will not solve it for you. You must tell ORM what type.

I am not an ORM / Eloquent expert, but I think you expect too much from ORM. ORM does not have to guess what you want to do. This helps you manage relationships or objects, but does not bind objects unless you tell them about it.

However, you can try using a mutator. You can add a question to your model:

 public function setTypeAttribute($value) { $value->save(); $this->attributes['type_id'] = $value->id } 

and now it should be possible to use $q->type = $t; (However, I have not tested it)

0
source

Source: https://habr.com/ru/post/976205/


All Articles