Phương pháp `SyncwithoutDetaching` trong Laravel được thiết kế để thêm các mối quan hệ mới vào bảng xoay vòng nhiều đến mà không cần loại bỏ bất kỳ mối quan hệ nào. Về cách nó xử lý ID trùng lặp, đây là một lời giải thích chi tiết:
- Khi bạn gọi `SyncwithoutDetaching` với một mảng ID, Laravel sẽ chỉ đính kèm những ID chưa có trong bảng trục cho mối quan hệ đó. Nó không loại bỏ các mối quan hệ hiện có, không giống như phương thức `sync` tiêu chuẩn, tách ra bất kỳ ID nào không có trong mảng được cung cấp [1] [5] [6].
- Tuy nhiên, `SyncwithoutDetaching` vốn không ngăn chặn các bản sao nếu bảng trục hoặc logic ứng dụng của bạn cho phép chúng. Nếu bảng Pivot không có ràng buộc duy nhất về sự kết hợp của các khóa nước ngoài, có thể chèn các mục trùng lặp nếu phương thức được gọi là không chính xác hoặc nếu lược đồ cơ sở dữ liệu cho phép nó [3] [7] [8].
- Để tránh các bản sao, nên thực thi một khóa tổng hợp duy nhất trên các cột bảng Pivot (ví dụ: hai cột khóa nước ngoài) ở cấp cơ sở dữ liệu. Điều này đảm bảo rằng các nỗ lực chèn các hàng trùng lặp sẽ thất bại và bạn có thể xử lý các ngoại lệ như vậy trong ứng dụng của mình [8].
- Bên trong, `SyncWithOutDetaching` hoạt động bằng cách gọi phương thức` đồng bộ hóa với tham số thứ hai được đặt thành `false ', có nghĩa là" không tách rời. " Điều này khiến nó thêm các mục mới mà không cần loại bỏ các mục hiện có. Nó kiểm tra các ID hiện có và chỉ chèn những cái bị thiếu, vì vậy nó thường ngăn chặn việc thêm các bản sao trong quá trình hoạt động nếu mảng đầu vào không chứa các bản sao [1] [6].
- Nếu sao chép vẫn xuất hiện, nó thường là do:
- Mảng đầu vào chứa ID trùng lặp.
- Thiếu các ràng buộc cấp cơ sở dữ liệu.
- Sử dụng `đính kèm ()` thay vì `SyncWithOutDetaching ()`, vì `bám ()` luôn thêm các hàng mới bất kể các hàng hiện có, có khả năng gây ra các bản sao [6] [7].
Tóm lại, `SyncWithOutDetaching` tránh thêm các mối quan hệ trùng lặp trong quá trình hoạt động của nó bằng cách chỉ đính kèm ID chưa liên quan, nhưng nó dựa vào các ràng buộc đầu vào và cơ sở dữ liệu thích hợp để ngăn chặn hoàn toàn các bản sao. Thêm một chỉ mục duy nhất trên bảng Pivot là cách thực hành tốt nhất để đảm bảo không có hàng trùng lặp có thể tồn tại. Nếu các bản sao xảy ra, nó thường chỉ ra các ràng buộc bị thiếu hoặc sử dụng không đúng các phương thức liên quan như `đính kèm`.
Phương pháp này đặc biệt hữu ích khi bạn muốn thêm các mối quan hệ mà không ảnh hưởng đến các mối quan hệ hiện có và không có rủi ro các mục trùng lặp nếu được sử dụng chính xác với thiết kế cơ sở dữ liệu phù hợp.
Trích dẫn:
[1] https://stackoverflow.com/questions/17472128/preventing-laravel-adding-multiple-records-to-a-pivot-table
[2] https://laracasts.com/discuss/channels/laravel/many-to-many-sync-method-creates-duplicates-is-this-really-the-right-way-to-do-it
[3] https://github.com/laravel/framework/issues/21639
[4] https://laracasts.com/discuss/channels/eloquent/belongstomany-and-wanted-duplicates
.
[6] https://stackoverflow.com/questions/62104188/laravel-eloquent-attach-vs-syncwithoutdetaching
[7] https://www.youtube.com/watch?v=Dcrisowswti
[8] https://github.com/laravel/framework/issues/14270