2014-10-03 19 views
6

nền

Do chúng tôi có hai bảng sau đây type_id tham chiếu một hàng trong kiểu câu hỏi:Gắn một mô hình hasOne vào một kiểu Laravel/hùng biện mà không chỉ định id

câu hỏi

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

questionType

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

với các mô hình hùng biện như sau:

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

class QuestionType extends Model { 
} 

Câu hỏi 1

Làm thế nào tôi có thể thêm một câu hỏi mới tham chiếu đến một loại câu hỏi hiện mà không tay làm bất cứ điều gì với id? Ví dụ các công việc sau nhưng là xấu xí imo kể từ khi tôi phải tự gán các loại câu hỏi tương ứng id:

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

Chúng tôi từng nghĩ có một cách để cho các ORM xử lý các id-chuyển nhượng (không phải là điểm để tránh nội dung như thế này với ORMs), một cái gì đó dọc theo dòng (này không làm việc trong hùng biện ORM):

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

Câu hỏi 2

Liên quan đến câu hỏi 1, làm thế nào tôi sẽ đi về việc thêm một q mới uestion tham chiếu đến loại câu hỏi mới mà không tự làm bất kỳ điều gì có id? Tương tự như vậy tôi tưởng tượng cái gì đó dọc theo dòng:

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

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

Ở đây tôi muốn $q->save() để cứu cả hai loại mới câu hỏi và câu hỏi (hoặc một cái gì đó tương tự).

Các công trình sau đây, nhưng một lần nữa tôi gán id bản thân mình mà tôi tin rằng ORM nên xử lý:

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

Tôi đã thử chơi với kết hợp khác nhau của save(), update() phương pháp mà không may mắn. Tôi cũng tìm kiếm attach() tồn tại trên các mối quan hệ hasMany nhưng dường như bị thiếu trong hasOne.

+0

'attach' là' belongsToMany' (nhiều-nhiều với trục) phương pháp, vì vậy nó sẽ không hoạt động trên 'quan hệ hasMany'. 'hasOne' /' hasMany' cung cấp phương thức 'save', khá hợp lý, vì nó phải lưu mô hình khi bạn thay đổi trường của nó (khóa ngoài). –

Trả lời

10

Trước hết, bạn hiểu lầm mối quan hệ bạn tham khảo.

Dưới đây là những gì bạn cần:

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

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

sau đó bạn có thể liên kết chúng lại với nhau như thế này:

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

Bạn có thể vượt qua một cách rõ ràng một id để kết hợp cũng như:

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

Bạn không thể thực hiện việc này:

$question->questionType = $someQuestionType; 

cho cách này Eloquent xử lý các thuộc tính mô hình, không phải mối quan hệ.


Câu hỏi 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(); 
+0

Cảm ơn rất nhiều Jarek! Có vẻ như tôi đã trộn lẫn ngữ nghĩa của 'hasOne' và' dependsTo'. Trong tâm trí của tôi '$ this-> hasOne ('QuestionType')' trong đó '$ this' là một' Question' có nghĩa là _Question_ có một _QuestionType_. Sau khi tất cả những gì nó ngụ ý khi bạn thực sự nó to phải không ?. Nhưng dường như đó là cách khác xung quanh - khó hiểu! – olerass

+0

@olerass Nó có thể gây hiểu lầm ngay từ đầu. Nhưng hãy nghĩ về nó - thực sự là một câu hỏi có một loại? Không, nó thuộc về một loại và đó là những gì Eloquent ngụ ý. –

+0

Tôi biết đây là một chủ đề cũ, nhưng tôi có một giải pháp mà bạn có thể trực tiếp đặt loại câu hỏi với '$ question-> questionType = $ someQuestionType;'. Mã: [Pastebin] (https://pastebin.com/BLX7TzUf) –

0

Trả lời câu hỏi 1 đối với tôi cả hai phương pháp là tốt, bạn không cần phải thay đổi bất cứ điều gì.

Trả lời câu hỏi 2 bạn nên làm điều đó như bạn thấy. ORM sẽ không tự động tạo QuestionType cho đến khi bạn sử dụng phương pháp save thủ công.

Ví dụ, nếu bạn sử dụng mã:

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

gì ORM nên quyết định? Câu hỏi không được kết nối với bất kỳ $t hoặc $t2 để ORM sẽ không quyết định điều đó cho bạn.Bạn cần phải nói cho ORM biết loại đó là gì.

Tôi không phải là một ORM/hùng biện chuyên gia nhưng tôi nghĩ rằng bạn mong đợi quá nhiều từ ORM. ORM không nên đoán bạn muốn làm gì. Nó giúp bạn quản lý các quan hệ hoặc các đối tượng nhưng nó sẽ không liên kết các đối tượng nếu bạn không bảo nó làm như vậy.

Bạn tuy nhiên có thể thử với mutator. Bạn có thể thêm vào mô hình Câu hỏi của bạn:

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

và bây giờ chúng ta có thể sử dụng $q->type = $t; (Tuy nhiên tôi đã không kiểm tra nó)

+0

Về câu hỏi 1: phương pháp thứ hai là mã giả, nó không hoạt động trong Laravel (Eloquent ORM). Hoặc ít nhất, tôi không biết làm thế nào để làm điều đó. Bạn có? Về câu hỏi 2: bạn đang kết nối Câu hỏi với $ t tại '$ q-> type = $ t', vì vậy tôi không chắc tôi hiểu mối lo ngại của bạn về những gì ORM nên quyết định. Tất nhiên nó sẽ tiết kiệm $ t và $ q tại '$ q-> save()', và nếu bạn không kết nối $ t2 với bất cứ thứ gì hoặc lưu nó theo cách thủ công thì nó sẽ không được lưu. – olerass

Các vấn đề liên quan