Laravel nhiều đến nhiều đồng bộ hóa

Trước hết Laravel là một framework tuyệt vời. Tôi thực sự thích làm việc với nó và nó là công cụ số một của tôi để phát triển các ứng dụng web. Tuy nhiên, tuyệt vời như thế nào, vẫn có một số vấn đề rắc rối đây đó có thể cắn bạn một cách bất ngờ và cả trong thời điểm tồi tệ nhất.

Vì vậy, lời khuyên cá nhân của tôi dành cho bạn — tìm hiểu thêm về các công cụ bạn đang sử dụng. Đánh giá mã, bài viết, video, bất kỳ thứ gì giúp bạn hiểu điều gì đang diễn ra bên trong ít nhất ở mức cơ bản. Trong những trường hợp cụ thể hơn, không có cách nào khác ngoài việc tự mình xem mã

Như một phần thưởng, bạn có thể học được một hoặc hai điều từ nó;]

Trong quá trình phát triển Laravel, tôi đã nhiều lần rơi vào tình huống như vậy, nhưng ở đây tôi muốn nói về một trường hợp cụ thể.

Như bạn có thể biết, Eloquent có nhiều phương thức trợ giúp để làm việc với các mối quan hệ. Và họ làm cho cuộc sống của bạn dễ dàng hơn… cho đến khi họ không

Một trong những người trợ giúp như vậy là phương pháp sync[] hoặc trong trường hợp của chúng tôi, đó là phương pháp

composer require korridor/laravel-hasmany-sync
0. Nói tóm lại, nó giúp bạn đồng bộ hóa mối quan hệ nhiều-nhiều giữa mô hình A cụ thể và nhóm mô hình B theo cách

  • các mô hình B duy nhất sẽ được gán cho mô hình A là những mô hình trong nhóm đã nhận —sync[]
  • chỉ những mẫu B còn thiếu từ nhóm nhận được mới được chỉ định cho mẫu A —
    composer require korridor/laravel-hasmany-sync
    0

Âm thanh tốt, phải không?

Chúng tôi đã sử dụng phương pháp

composer require korridor/laravel-hasmany-sync
0 cho bất kỳ trường hợp nào chúng tôi muốn thêm một mô hình mới vào mối quan hệ nhưng chỉ những mô hình còn thiếu. Trường hợp hoàn hảo cho phương pháp trợ giúp này

Tất cả mọi thứ làm việc tuyệt vời

Tua đi một vài năm và đột nhiên, yêu cầu đơn giản là gắn một mô hình vào một mô hình khác không thành công với ngoại lệ "Hết bộ nhớ". Trong một sản xuất

Nói “Xin chào” với các vấn đề về khả năng mở rộng

Mã này khá đơn giản

$list->customers[]->syncWithoutDetaching[$customers_to_attach];

Dòng duy nhất đó đã tiêu thụ một lượng lớn bộ nhớ

Sau một số nghiên cứu, tôi phát hiện ra rằng lý do cho điều đó là theo cách mà phương pháp sync[] hoạt động. Tôi biết tôi đang nói về

composer require korridor/laravel-hasmany-sync
0, nhưng nó chỉ là bí danh cho trường hợp sử dụng cụ thể của phương thức sync[]

Phương thức sync[] thực sự làm gì - nó tải tất cả các mã định danh trục hiện có vào một mảng và sau đó bắt đầu thực hiện một số thao tác trên mảng đó và mảng các mã định danh nhận được trước đó để đính kèm. Với một số bản sao mảng bổ sung trên đường

Điều này tốt khi bạn làm việc với vài trăm hàng, nhưng không tốt lắm khi bạn phải tải vài trăm nghìn hoặc thậm chí nhiều hàng hơn

Vì vậy, hãy cẩn thận khi bạn sử dụng trình trợ giúp này trong các ứng dụng của mình, đặc biệt là khi bạn muốn nó mở rộng đáng kể

Một số cách để đạt được chức năng mong muốn mà không đạt đến giới hạn bộ nhớ

  • kiểm tra sự tồn tại của chỉ những mô hình bạn muốn đính kèm và sau đó sử dụng phương pháp sync[]0 trên những mô hình bị thiếu
  • đối với một số lượng lớn các mô hình để đính kèm, có lẽ tốt hơn là sử dụng các công việc và chia nhỏ các mô hình
  • tạo khóa chính trên hai khóa ngoại và bắt các ngoại lệ từ DB [Tôi đã thấy các đề xuất như vậy, mặc dù theo ý kiến ​​của tôi thì không thuận tiện khi bạn đang cố gắng đính kèm một số lượng lớn mô hình]
  • viết một số phương pháp sync[] tùy chỉnh với logic của riêng bạn
  • làm việc trực tiếp với DB thay vì sử dụng những người trợ giúp hùng hồn

Tôi chắc rằng có hàng chục cách khác để tối ưu hóa điều đó. Hãy cho tôi biết trong phần nhận xét trường hợp sử dụng của bạn là gì và cách bạn giải quyết nó

Ghi chú. Gói này là một nhánh của alfa6661/laravel-hasmany-sync. Tôi đã thêm các bài kiểm tra và tôi dự định sẽ thêm nhiều tính năng hơn trong tương lai

Cho phép phương thức đồng bộ hóa cho Laravel Có nhiều mối quan hệ

Cài đặt

Bạn có thể cài đặt gói qua trình soạn thảo bằng lệnh sau

composer require korridor/laravel-hasmany-sync

Yêu cầu

Gói này được thử nghiệm cho các phiên bản Laravel và PHP sau

  • 9. * [PHP 8. 0, 8. 1]
  • 8. * [PHP 7. 4, 8. 0, 8. 1]
  • 7. * [PHP 7. 2, 7. 3, 7. 4]
  • 6. * [PHP 7. 2, 7. 3]

Cách sử dụng

Thiết lập mối quan hệ HasMany

class Customer extends Model
{
    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function contacts[]
    {
        return $this->hasMany[CustomerContact::class];
    }
}

Bạn có thể truy cập phương thức đồng bộ hóa như thế này

$customer->contacts[]->sync[[
    [
        'id' => 1,
        'name' => 'Alfa',
        'phone_number' => '123',
    ],
    [
        'id' => null,
        'name' => 'Adhitya',
        'phone_number' => '234,
    ]
]];

Phương thức đồng bộ chấp nhận một mảng dữ liệu để đặt trên bảng trung gian. Mọi dữ liệu không có trong mảng đã cho sẽ bị xóa khỏi bảng trung gian. Vì vậy, sau khi thao tác này hoàn tất, chỉ có dữ liệu trong mảng đã cho sẽ tồn tại trong bảng trung gian

Đồng bộ hóa mà không xóa

Nếu bạn không muốn xóa dữ liệu hiện có, bạn có thể chuyển giá trị sai cho tham số thứ hai trong phương thức đồng bộ hóa

$customer->contacts[]->sync[[
    [
        'id' => 1,
        'name' => 'Alfa',
        'phone_number' => '123',
    ],
    [
        'id' => null,
        'name' => 'Adhitya',
        'phone_number' => '234,
    ]
], false];

Ví dụ sử dụng trong bộ điều khiển

class CustomersController extends Controller
{
    /**
     * Update the specified resource in storage.
     *
     * @param  CustomerRequest  $request
     * @param  Customer $customer
     * @return \Illuminate\Http\Response
     */
    public function update[CustomerRequest $request, Customer $customer]
    {
        DB::transaction[function [] use [$customer, $request] {
            $customer->update[$request->all[]];
            $customer->contacts[]->sync[$request->get['contacts', []]];
        }];

        return redirect[]->route['customers.index'];
    }
}

Đóng góp

Tôi mở cho các đề xuất và đóng góp. Chỉ cần tạo một vấn đề hoặc yêu cầu kéo

Môi trường docker cục bộ

Thư mục

class Customer extends Model
{
    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function contacts[]
    {
        return $this->hasMany[CustomerContact::class];
    }
}
0 chứa môi trường docker cục bộ để phát triển. Không gian làm việc docker đã cài đặt trình soạn thảo và xdebug

docker-compose run workspace bash

thử nghiệm

Lệnh

class Customer extends Model
{
    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function contacts[]
    {
        return $this->hasMany[CustomerContact::class];
    }
}
1 chạy tất cả các bài kiểm tra với phpunit. Lệnh
class Customer extends Model
{
    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function contacts[]
    {
        return $this->hasMany[CustomerContact::class];
    }
}
2 chạy tất cả các bài kiểm tra với phpunit và tạo báo cáo bảo hiểm vào thư mục
class Customer extends Model
{
    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function contacts[]
    {
        return $this->hasMany[CustomerContact::class];
    }
}
3

Định dạng mã/linting

Lệnh

class Customer extends Model
{
    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function contacts[]
    {
        return $this->hasMany[CustomerContact::class];
    }
}
0 định dạng mã bằng php-cs-fixer. Lệnh
class Customer extends Model
{
    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function contacts[]
    {
        return $this->hasMany[CustomerContact::class];
    }
}
1 kiểm tra code bằng phpcs

Làm cách nào để tạo mối quan hệ nhiều đối nhiều trong Laravel?

vậy hãy tạo như bên dưới. .
di chuyển bảng người dùng. Lược đồ. tạo ['người dùng', hàm [Bản thiết kế $bảng] {.
di chuyển bảng vai trò. Lược đồ. tạo ['vai trò', chức năng [Bản thiết kế $table] {.
di chuyển bảng role_user. .
Mô hình người dùng. .
Người mẫu. .
Mô hình vai trò người dùng. .
*** Nhấp vào nó và đọc chi tiết về các loại RelationShip

Sự khác biệt giữa đính kèm và đồng bộ hóa trong Laravel là gì?

Hàm đính kèm chỉ thêm các bản ghi vào bảng Pivot. Chức năng đồng bộ hóa thay thế bản ghi hiện tại bằng bản ghi mới . Điều này rất hữu ích để cập nhật một mô hình.

Làm cách nào để sử dụng phương thức đồng bộ hóa trong Laravel?

Nói một cách đơn giản, chúng ta có thể nói. sync[] tương tự như phương thức attachment[] và nó cũng sử dụng để đính kèm các mô hình liên quan. phương thức sync[] chấp nhận một mảng ID để đặt trên bảng tổng hợp . Nếu các mô hình không tồn tại trong mảng, phương thức đồng bộ hóa sẽ xóa các mô hình khỏi bảng và chèn các mục mới vào bảng tổng hợp.

Làm cách nào để tạo mối quan hệ giữa hai bảng trong Laravel?

Để xác định mối quan hệ, trước tiên chúng ta cần xác định phương thức post[] trong mô hình Người dùng . Trong phương thức post[], chúng ta cần triển khai phương thức hasOne[] trả về kết quả. Hãy hiểu mối quan hệ 1-1 thông qua một ví dụ. Đầu tiên, chúng tôi thêm cột mới [user_id] vào bảng hiện có có tên là bài đăng.

Chủ Đề