将 hasOne 模型附加到另一个 Laravel/Eloquent 模型而不指定 id

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26178049/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 10:14:21  来源:igfitidea点击:

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

laravellaravel-4eloquent

提问by olerass

Background

背景

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

鉴于我们有以下两个表,其中 type_id 引用questionType 中的一行:

question

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

questionType

问题类型

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

with the following Eloquent models:

使用以下 Eloquent 模型:

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

class QuestionType extends Model {
}

Question 1

问题 1

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

如何添加一个引用现有问题类型的新问题,而无需手动对 id 进行任何操作?例如,以下工作但很丑陋,因为我必须手动分配相应的问题类型 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):

有人会认为有一种方法可以让 ORM 处理 id 分配(这不是在 ORM 中避免此类事情的重点吗?),类似于(这在 Eloquent ORM 中不起作用):

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

Question 2

问题2

In relation to question 1, how would I go about adding a new question that references a newquestion type without manually doing anything with ids? Similarly I imagine something along the lines of:

关于问题 1,我将如何添加一个引用问题类型的问题,而无需手动对 id 进行任何操作?同样,我想象了一些类似的东西:

$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).

在这里,我想$q->save()同时保存新的问题类型和问题(或类似的问题)。

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

以下工作,但我再次自己分配我相信ORM应该处理的id:

$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 hasManyrelationships but seem to be missing in hasOne.

我尝试过使用save(),update()方法的不同组合而没有运气。我还寻找attach()存在于hasMany关系中但似乎在hasOne.

回答by Jarek Tkaczyk

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:

您也可以显式传递 id 以进行关联:

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


You can't do this:

你不能这样做:

$question->questionType = $someQuestionType;

for this way Eloquent handles model attributes, not relations.

Eloquent 以这种方式处理模型属性,而不是关系。



Question 2:

问题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();

回答by Marcin Nabia?ek

Answering question 1 for me both methods are good, you don't need to change anything.

为我回答问题 1 两种方法都很好,您无需更改任何内容。

Answering question 2 you should do it as you showed. ORM won't create automatically QuestionTypeuntil you use manually savemethod.

回答问题 2 你应该按照你展示的那样做。QuestionType在您使用手动save方法之前,ORM 不会自动创建。

For example if you used 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 ORM should decide? Question isn't connected to any of $tor $t2so ORM won't decide it for you. You need to tell ORM what's the type.

ORM 应该决定什么?问题是没有连接到任何的$t$t2使ORM不会决定给你。你需要告诉 ORM 是什么类型。

I'm not an ORM/Eloquent expert but I think you expect too much from ORM. ORM shouldn't guess what you want to do. It help you manage relations or objects but it won't associate objects if you don't tell it to do so.

我不是 ORM/Eloquent 专家,但我认为您对 ORM 期望过高。ORM 不应该猜测你想做什么。它可以帮助您管理关系或对象,但如果您不告诉它,它不会关联对象。

You could however try with mutator. You could add to your Question model:

但是,您可以尝试使用 mutator。您可以添加到您的问题模型:

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 haven't tested it)

现在应该可以使用了$q->type = $t;(不过我还没有测试过)