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-sync0. 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-sync0 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-sync0, 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