Laravel, sync () - làm thế nào để đồng bộ hóa một mảng và cũng chuyển các trường tổng hợp bổ sung?


81

Tài liệu chính thức của Laravel có sync()chức năng này:

$user->roles()->sync( array( 1, 2, 3 ) );

Bạn cũng có thể liên kết các giá trị bảng tổng hợp khác với các ID đã cho:

$user->roles()->sync( array( 1 => array( 'expires' => true ) ) );

Trong ví dụ sau, chỉ có một hàng trụ duy nhất được thêm vào. Điều tôi không hiểu là làm cách nào tôi có thể liên kết các bản ghi bảng tổng hợp khác nếu có nhiều hơn một hàng được đồng bộ hóa?

Cảm ơn trước.


Câu trả lời dưới đây đã không giúp tôi thông qua .. bạn có thể vui lòng đăng các giải pháp của bạn cho điều đó? Cảm ơn!
Evis

Câu hỏi hay ... tất cả các gia sư đều có đầy đủ những điều cơ bản.
Shahid Karimi

Câu trả lời:


35

Điều này phù hợp với tôi

foreach ($photos_array as $photo) {

    //collect all inserted record IDs
    $photo_id_array[$photo->id] = ['type' => 'Offence'];  

}

//Insert into offence_photo table
$offence->photos()->sync($photo_id_array, false);//dont delete old entries = false

2
Ủng hộ cái này vì nó đẹp và sạch sẽ và tôi nghi ngờ rằng nó sẽ rất dễ dàng cho bất kỳ nhà phát triển nào sau đó hiểu và sửa đổi.
DevBodin

Bạn cũng có thể thay thế ->sync($photo_id_array, false)thành ->syncWithoutDetaching($photo_id_array). Cũng ủng hộ vì đây là giải pháp thanh lịch nhất.
Musa

147

Để có syncnhiều mô hình cùng với dữ liệu tổng hợp tùy chỉnh, bạn cần có:

$user->roles()->sync([ 
    1 => ['expires' => true],
    2 => ['expires' => false],
    ...
]);

I E.

sync([
    related_id => ['pivot_field' => value],
    ...
]);

biên tập

Trả lời bình luận:

$speakers  = (array) Input::get('speakers'); // related ids
$pivotData = array_fill(0, count($speakers), ['is_speaker' => true]);
$syncData  = array_combine($speakers, $pivotData);

$user->roles()->sync($syncData);

1
Jarek nhưng nếu tôi có ví dụ $speakers = \Input::get( 'speakers' )(trong đó $ speaker trở thành một mảng), và sau đó muốn chuyển $speakerscùng với =>array( 'is_speaker' => true)?
Томица Кораћ

1
Nếu không thì sao. Bạn tạo mảng đồng bộ như hình trên. Xây dựng mảng của bạn bằng idscác khóa hoặc làm theo cách này trong biểu mẫu HTML của bạn.
Jarek Tkaczyk

Jarek, my \ Input :: get ('eakers ') đang trả về một mảng id. Có phải thứ gì đó giống như công việc này không:$training->users()->sync( array( $speakers => array( 'is_speaker' => true ) ) )
Томица Кораћ

1
@JarekTkaczyk Cảm ơn! Câu trả lời cho nhận xét chính là những gì tôi đang tìm kiếm!
Pathros

1
@JarekTkaczyk trông đẹp mắt, nhưng mỗi mục được cập nhật \ được chèn với một truy vấn riêng biệt, điều này hơi đáng thất vọng vì nó sẽ ảnh hưởng đến hiệu suất.
tylik

4

Gắn / tách

Eloquent cũng cung cấp một số phương pháp trợ giúp bổ sung để làm việc với các mô hình liên quan thuận tiện hơn. Ví dụ, hãy tưởng tượng một người dùng có thể có nhiều vai trò và một vai trò có thể có nhiều người dùng. Để đính kèm vai trò cho người dùng bằng cách chèn bản ghi vào bảng trung gian kết hợp các mô hình, hãy sử dụng phương pháp đính kèm:

$user = App\User::find(1);

$user->roles()->attach($roleId);

Khi đính kèm mối quan hệ vào một mô hình, bạn cũng có thể chuyển một mảng dữ liệu bổ sung để chèn vào bảng trung gian:

$user->roles()->attach($roleId, ['expires' => $expires]);

Bạn cũng có thể sử dụng Đồng bộ hóa nếu bạn muốn xóa các vai trò cũ và chỉ giữ các vai trò mới mà bạn đang đính kèm hiện tại

$user->roles()->sync([1 => ['expires' => $expires], 2 => ['expires' => $expires]);

Hành vi mặc định có thể được thay đổi bằng cách chuyển "false" làm đối số thứ hai. Thao tác này sẽ gắn các vai trò với id 1,2,3 mà không ảnh hưởng đến các vai trò hiện có.

Trong chế độ này, đồng bộ hóa hoạt động tương tự như phương pháp đính kèm.

$user->roles()->sync([1 => ['expires' => $expires], 2 => ['expires' => $expires], false);

Tham khảo: https://laravel.com/docs/5.4/eloquent-relationships


2

Thêm đặc điểm sau vào dự án của bạn và nối nó vào lớp mô hình của bạn như một đặc điểm. Điều này rất hữu ích, bởi vì điều này bổ sung thêm chức năng sử dụng nhiều trục. Có lẽ ai đó có thể làm sạch điều này một chút và cải thiện nó;)

namespace App\Traits;

trait AppTraits
{
    /**
     * Create pivot array from given values
     *
     * @param array $entities
     * @param array $pivots
     * @return array combined $pivots
     */
    public function combinePivot($entities, $pivots = [])
    {
        // Set array
        $pivotArray = [];
        // Loop through all pivot attributes
        foreach ($pivots as $pivot => $value) {
            // Combine them to pivot array
            $pivotArray += [$pivot => $value];
        }
        // Get the total of arrays we need to fill
        $total = count($entities);
        // Make filler array
        $filler = array_fill(0, $total, $pivotArray);
        // Combine and return filler pivot array with data
        return array_combine($entities, $filler);
    }
}

Mô hình:

namespace App;

use Illuminate\Database\Eloquent\Model;

class Example extends Model
{
    use Traits\AppTraits;
    // ...
}

Sử dụng:

// Get id's
$entities = [1, 2, 3];
// Create pivots
$pivots = [
    'price' => 634,
    'name'  => 'Example name',
];
// Combine the ids and pivots
$combination = $model->combinePivot($entities, $pivots);
// Sync the combination with the related model / pivot
$model->relation()->sync($combination);

1
Tôi thích suy nghĩ của bạn-- tốt hơn là biến nó thành thứ có thể tái sử dụng, thay vì sao chép vào lần sau khi vấn đề này xuất hiện - mặc dù tôi khuyên bạn nên biến nó thành một chức năng trợ giúp để nó có thể được sử dụng ở mọi nơi và với bất kỳ mô hình nào.
DevBodin

0

Đơn giản chỉ cần nối các trường của bạn và giá trị của chúng vào các phần tử:

$user->roles()->sync([
   1 => ['F1' => 'F1 Updated']
]);

0
$data = array();
foreach ($request->planes as $plan) {
 $data_plan = array($plan => array('dia' => $request->dia[$plan] ) );                
 array_push($data,$data_plan);    
}
$user->planes()->sync($data);

8
Khi trả lời một bài đăng cũ, sẽ rất hữu ích nếu bạn có thể cung cấp một số ngữ cảnh cho câu trả lời của mình thay vì chỉ mã, vì nó có thể làm cho nó hữu ích hơn cho người khác.
David Buck

Xem David Bucks bình luận. Ngoài ra, bao gồm các phiên bản phần mềm và / hoặc hệ thống và / hoặc thư viện; cách duy nhất để ngăn chặn việc phản đối hoặc xóa câu trả lời.
ZF007
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.