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

时间:2014-10-03 11:20:48

标签: laravel laravel-4 eloquent

背景

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

问题

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

questionType

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-assignment(不是用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,我如何添加引用问题类型的新问题,而无需手动执行任何有关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()同时保存新问题类型和问题(或类似内容)。

以下作品,但我再次分配我自己的ID,我相信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();

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

2 个答案:

答案 0 :(得分:16)

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

以下是您的需求:

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

答案 1 :(得分:0)

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

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

例如,如果您使用了代码:

$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;(但我没有测试过它)