Laravel lưu / cập nhật nhiều mối quan hệ


85

Bất cứ ai có thể giúp tôi làm thế nào để tiết kiệm nhiều mối quan hệ? Tôi có nhiệm vụ, người dùng có thể có nhiều tác vụ và tác vụ có thể có nhiều người dùng (nhiều đến nhiều), Điều tôi muốn đạt được là trong biểu mẫu cập nhật, quản trị viên có thể chỉ định nhiều người dùng cho các tác vụ cụ thể. Điều này được thực hiện thông qua đầu vào nhiều lựa chọn html

name="taskParticipants[]"

Điểm bắt buộc ở đây là thông qua cùng một biểu mẫu (đầu vào), bạn có thể thêm / bớt người dùng, đó là lý do tại sao tôi phải sử dụng sync (). Có lẽ tôi nên bắt đầu lại từ đầu nhưng không biết bắt đầu từ đâu ...

Đây là mô hình Người dùng của tôi:

public function tasks()
{
    return $this->belongsToMany('Task','user_tasks');
}

Mô hình nhiệm vụ

public function taskParticipants()
{
    return $this->belongsToMany('User','user_tasks');
}

TaskController

public function update($task_id)
{
    if (Input::has('taskParticipants'))
    {
        foreach(Input::get('taskParticipants') as $worker)
        {
            $task2 = $task->taskParticipants->toArray();
            $task2 = array_add($task2,$task_id,$worker);
            $task->taskParticipants()->sync(array($task2));
        }
    }
}

Đây là cấu trúc của bảng nhiệm vụ id | tiêu đề | hạn chót

user_tasks
id|task_id|user_id

Tôi đã cập nhật mã của mình. liên kết
SuperManSL

4
$workers = Input::get('taskParticipants'); $task->taskParticipants()->sync($workers);và đó là tất cả những gì bạn cần, miễn là bạn chuyển từ biểu mẫu đó tất cả người dùng, được giao cho nhiệm vụ.
Jarek Tkaczyk

@JarekTkaczyk Cảm ơn, Điều đó thật kỳ diệu.
Ryu_hayabusa

Câu trả lời:


191

tldr; Sử dụng syncvới thông số thứ 2false


Mối quan hệ nhiều-nhiều có belongsToManytrên cả hai mô hình:

// Task model
public function users()
{
  return $this->belongsToMany('User', 'user_tasks'); // assuming user_id and task_id as fk
}

// User model
public function tasks()
{
  return $this->belongsToMany('Task', 'user_tasks');
}

Để thêm quan hệ mới sử dụng attachhoặc sync.

Sự khác biệt giữa hai là:

1 attach sẽ thêm hàng mới trên bảng tổng hợp mà không cần kiểm tra xem nó đã ở đó chưa. Thật tốt khi bạn có dữ liệu bổ sung được liên kết với mối quan hệ đó, ví dụ:

UserExamđược liên kết với bảng tổng hợpattempts: id, user_id, exam_id, score

Tôi cho rằng đây không phải là điều bạn cần trong tình huống của mình:

$user->tasks()->getRelatedIds(); // [1,2,3,4,5,6]

$user->tasks()->attach([5,6,7]);
// then
$user->tasks()->getRelatedIds(); // [1,2,3,4,5,6,5,6,7]

2 sync mặt khác, sẽ xóa tất cả các quan hệ và thiết lập lại chúng:

$user->tasks()->getRelatedIds(); // [1,2,3,4,5,6]

$user->tasks()->sync([1,2,3]);
// then
$user->tasks()->getRelatedIds(); // [1,2,3]

hoặc nó sẽ thiết lập các quan hệ mới mà không tách AND trước đó mà không thêm các bản sao:

$user->tasks()->sync([5,6,7,8], false); // 2nd param = detach
// then
$user->tasks()->getRelatedIds(); // [1,2,3,4,5,6,7,8]

8
Sẽ thật tuyệt nếu điều đó được ghi lại trong các tài liệu chính hơn là tài liệu API! Đá lên. +1.
ceejayoz,

Tôi thực sự thích giải pháp thứ hai với đồng bộ hóa và tham số thứ hai. Như tôi đã nói trong phần bình luận dưới đây, tôi không thể không sử dụng detach. Chuyện là admin có thể giao nhiệm vụ cho người dùng. Anh ấy chọn người dùng từ menu thả xuống (nhiều), trường là người tham gia []. Vì vậy ...: Bước 1: quản trị viên gán nhiệm vụ A cho ba người dùng (phương pháp của bạn hoạt động, chúng tôi có 3 bản ghi trong DB) Bước 2: quản trị viên cập nhật tác vụ A và thêm hai người dùng (phương pháp của bạn hoạt động, chúng tôi có 5 bản ghi trong DB) bước 3: admin cập nhật nhiệm vụ Một và loại bỏ 1 người (phương pháp của bạn bị lỗi, chúng tôi vẫn có 5 người dùng thay vì 4) phương pháp cập nhật của tôi mã của tôi
SuperManSL

1
Bạn có thể đơn giản hóa truy vấn mối quan hệ của bạn chỉ $this->belongsToMany('User')nếu bạn sử dụng tên bàn theo thứ tự abc và số ít (do đó task_userthay vì user_tasks)
Kousha

@Rok nếu bạn luôn chuyển một mảng gồm tất cả người dùng có liên quan, thì hãy sử dụng syncvới việc tách ra, đừng lo lắng. Tôi khuyên bạn nên sử dụng tham số thứ 2 được đặt thành false bất cứ khi nào bạn muốn 'thêm nhiệm vụ mới cho người dùng' hoặc 'chỉ định người dùng cho một nhiệm vụ', khi bạn chuyển một idmô hình liên quan.
Jarek Tkaczyk

1
@FabioAntunes synctrả về một mảng với detached, attachedupdateddanh sách. attachkhông trả về bất cứ điều gì, nhưng trong cả hai trường hợp, bạn sẽ nhận được một ngoại lệ nếu điều gì đó không mong muốn xảy ra trong các cuộc gọi db.
Jarek Tkaczyk

106

Đây là ghi chú của tôi về cách lưu và cập nhật tất cả các mối quan hệ Hùng biện.

trong One to One :

Bạn phải sử dụng HasOne trên mô hình đầu tiên và BelongsTo trên mô hình thứ hai

để thêm bản ghi trên mô hình đầu tiên ( HasOne ), hãy sử dụng  chức năng lưu

thí dụ:    $post->comments()->save($comment);

để thêm bản ghi trên mô hình thứ hai ( BelongsTo ), hãy sử dụng  hàm liên kết

thí dụ:    $user->account()->associate($account);    $user->save();


trong Một đến Nhiều :

Bạn phải sử dụng HasMany trên mô hình đầu tiên và BelongsTo trên mô hình thứ hai

để thêm biểu ghi vào bảng đầu tiên ( HasMany ) sử dụng tiết kiệm  hoặc saveMany chức năng

thí dụ:    $post->comments()->saveMany($comments);

để thêm bản ghi trên mô hình thứ hai ( BelongsTo ), hãy sử dụng  hàm liên kết

thí dụ:    $user->account()->associate($account);    $user->save();


trong Nhiều đến Nhiều :

Bạn phải sử dụng  BelongsToMany trên mô hình đầu tiên và BelongsToMany trên mô hình thứ hai

để thêm bản ghi trên bảng tổng hợp, hãy sử dụng chức năng đính kèm hoặc đồng bộ hóa

  • cả hai hàm đều chấp nhận một ID hoặc một mảng ID 

  • sự khác biệt là đính kèm kiểm tra nếu bản ghi đã tồn tại trên bảng tổng hợp trong khi đồng bộ hóa thì không

thí dụ: $user->roles()->attach($roleId);


trong Đa hình Một đến Nhiều :

Bạn phải sử dụng  MorphMany trên mô hình chính và  MorphTo trên tất cả các mô hình (*** có thể)

để thêm bản ghi trên tất cả các mô hình khác, hãy sử dụng  lưu

thí dụ:    $course->tags()->save($tag);

bảng tổng hợp phải có các cột sau:

. ID mô hình chính

. (*** có thể) ID

. (*** có thể) Loại


trong Đa hình Nhiều đến Nhiều :

Bạn phải sử dụng  MorphByMany trên mô hình chính và  MorphToMany trên tất cả các mô hình (*** có thể)

để thêm các bản ghi trên tất cả các mô hình khác sử dụng tiết kiệm hoặc saveMany

thí dụ:    $course->tags()->save($tag);

thí dụ:    $course->tags()->saveMany([$tag_1, $tag_2, $tag_3]);

bảng tổng hợp phải có các cột sau:

. ID mô hình chính

. (*** có thể) ID

. (*** có thể) Loại


trong Has Many Through (phím tắt):

Bạn phải sử dụng HasManyThrough trên bảng đầu tiên và có quan hệ bình thường trên 2 bảng còn lại

điều này không hoạt động đối với các mối quan hệ ManyToMany (trong đó có bảng tổng hợp)

tuy nhiên có một giải pháp tốt và dễ dàng chỉ cho điều đó.


Đây là một bài báo tôi đã viết, lấy cảm hứng từ câu trả lời này. Điều quan trọng là kiểm tra nó: https://hackernoon.com/eloquent-relationships-cheat-sheet-5155498c209


Tôi thực sự đặt câu trả lời này khi họ đã có hơn 40 thích về câu trả lời chính xác, nhưng có tôi biết làm thế nào hữu ích này là dành cho tôi, vui bạn thích nó :)
Mahmoud Zalt

1
Tôi ước bạn biết rằng bạn là một vị cứu tinh
Chay22

1
đây là một câu trả lời tuyệt vời.
caro

1
làm thế nào để cập nhật một mối quan hệ có thể. u giải thích làm thế nào để thêm. bạn có thể vui lòng giải thích về bản cập nhật không? có một phương pháp để cập nhật các bản ghi giống như updateManymột cái gì đó như vậy? cảm ơn
Hamidreza

3

syncWithoutDetaching([$id_one, $id_two, $id_three]);là những gì bạn đang tìm kiếm. Trên thực tế, nó làm điều chính xác [ syncvới thông số thứ 2 false] làm!


0

Các syncchức năng obliterates các mối quan hệ thoát và làm cho mảng của bạn toàn bộ danh sách các mối quan hệ. attachThay vào đó, bạn muốn thêm các quan hệ mà không xóa những người khác.


Tôi không thể sử dụng tệp đính kèm vì tôi đang sử dụng mã này bên trong phương pháp cập nhật. Câu chuyện là quản trị viên có thể cập nhật nhiệm vụ và điền vào những người tham gia đầu vào [] với những người dùng sẽ tham gia vào nhiệm vụ. Vì vậy, tôi cần kiểm tra xem nó có tồn tại hay không và xóa (hoặc không thêm bản ghi mới) nó hoặc nếu nó không tồn tại, hãy thêm nó.
SuperManSL
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.