Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Attaching a hasOne model to another Laravel/Eloquent model without specifying id

Background

Given we have the following two tables where type_id references a row in questionType:

question

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

questionType

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

with the following Eloquent models:

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

class QuestionType extends Model {
}

Question 1

How can I add a new question that references an existing question type without manually doing anything with ids? For example the following works but is ugly imo since I have to manually assign the corresponding question type id:

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

One would think there was a way to let the ORM handle the id-assignment (isn't the point to avoid stuff like this with ORMs?), something along the lines of (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 would I go about adding a new question that references a new question type without manually doing anything with ids? Similarly I imagine something along the lines of:

$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'd like $q->save() to save both the new question type and question (or something similar).

The following works, but again I'm assigning the id myself which I believe the ORM should handle:

$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've tried playing with different combinations of save(), update() methods without luck. I also looked for attach() which exists on the hasMany relationships but seem to be missing in hasOne.

like image 919
olerass Avatar asked Oct 03 '14 11:10

olerass


People also ask

How can I join model in Laravel?

Laravel join accepts multiple parameters to the function and first parameter as table name and rest are columns constraints. DB::table('users') ->join('contacts', 'users.id', '=', 'contacts. user_id') ->join('orders', 'users.id', '=', 'orders. user_id') ->select('users.

What is with () in Laravel?

with() function is used to eager load in Laravel. Unless of using 2 or more separate queries to fetch data from the database , we can use it with() method after the first command. It provides a better user experience as we do not have to wait for a longer period of time in fetching data from the database.

What is the difference between hasOne and belongsTo Laravel?

The only difference between hasOne and belongsTo is where the foreign key column is located. Let's say you have two entities: User and an Account. In short hasOne and belongsTo are inverses of one another - if one record belongTo the other, the other hasOne of the first.


1 Answers

First off, you misunderstood the relation you refer to.

Here's 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 together like this:

$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 id to associate as well:

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

You can't do this:

$question->questionType = $someQuestionType;

for this way Eloquent handles model attributes, not relations.


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();
like image 126
Jarek Tkaczyk Avatar answered Oct 18 '22 16:10

Jarek Tkaczyk