【问题标题】:Attaching a hasOne model to another Laravel/Eloquent model without specifying id将 hasOne 模型附加到另一个 Laravel/Eloquent 模型而不指定 id
【发布时间】:2014-10-03 11:20:47
【问题描述】:

背景

假设我们有以下两个表,其中 type_id 引用了 questionType 中的一行:

问题

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

问题类型

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

使用以下 Eloquent 模型:

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

class QuestionType extends Model {
}

问题 1

如何添加一个引用现有问题类型的新问题而不手动对 id 进行任何操作?例如以下工作,但丑陋的 imo 因为我必须手动分配相应的问题类型 id:

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

有人会认为有一种方法可以让 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();

问题 2

关于问题 1,我将如何添加一个引用 new 问题类型的新问题,而无需手动对 id 进行任何操作?同样,我想像这样的事情:

$t = new QuestionType;
$t->name = 'Another type';

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

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

以下工作,但我再次自己分配我认为 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();

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

【问题讨论】:

  • attachbelongsToMany (带枢轴的多对多)方法,因此它不适用于 hasMany 关系。 hasOne/hasMany 提供save 方法,这很合逻辑,因为当你改变它的字段(外键)时你必须保存模型。

标签: laravel laravel-4 eloquent


【解决方案1】:

首先,您误解了您所指的关系。

这是你需要的:

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

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

然后您可以像这样将它们链接在一起:

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

您也可以显式传递一个 id 来关联:

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

你不能这样做:

$question->questionType = $someQuestionType;

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


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

【讨论】:

  • 非常感谢 Jarek!看来我混淆了hasOnebelongsTo 的语义。在我看来$this->hasOne('QuestionType') 其中$thisQuestion 意味着Question 有一个QuestionType。毕竟这就是当你真正大声的时候它所暗示的,对吧?但显然情况恰恰相反——令人困惑!
  • @olerass 一开始可能会产生误导。但是想一想——问题真的有类型吗?不,它属于一种类型,这就是 Eloquent 所暗示的。
  • 我知道这是一个旧线程,但我有一个解决方案,您可以直接使用$question->questionType = $someQuestionType; 设置问题类型。代码:Pastebin
  • 这帮助我克服了用户在我的 laravel 应用程序中拥有一个角色时遇到的问题
【解决方案2】:

对我来说回答问题 1 两种方法都很好,你不需要改变任何东西。

回答问题 2,您应该按照您的说明进行操作。在您手动使用save 方法之前,ORM 不会自动创建QuestionType

例如,如果您使用代码:

$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();

ORM 应该决定什么?问题未与$t$t2 中的任何一个相关联,因此 ORM 不会为您决定。你需要告诉 ORM 是什么类型。

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

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

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

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

【讨论】:

  • 关于问题1:第二种方法是伪代码,在Laravel(Eloquent ORM)中不起作用。或者至少,我不知道该怎么做。你?关于问题 2:您在 $q->type = $t 将 Question 连接到 $t,所以我不确定我是否理解您对 ORM 应该决定什么的担忧。当然,它应该在$q->save() 保存 $t 和 $q,如果你没有将 $t2 连接到任何东西或手动保存它,它不会被保存。
猜你喜欢
  • 2022-01-05
  • 2016-06-12
  • 1970-01-01
  • 2016-09-20
  • 1970-01-01
  • 2017-06-03
  • 2023-02-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多