iksaku/laravel-mass-update
Composer 安装命令:
composer require iksaku/laravel-mass-update
包简介
Update multiple Laravel Model records, each with different values, using a single query!
README 文档
README
Update multiple Laravel Model records, each with its own set of values, sending a single query to your database!
Installation
You can install the package via composer:
composer require iksaku/laravel-mass-update
Usage
In your model class, add the Iksaku\Laravel\MassUpdate\MassUpdatable trait:
use Illuminate\Database\Eloquent\Model; use Iksaku\Laravel\MassUpdate\MassUpdatable; class User extends Model { use MassUpdatable; // ... }
And that's all! Your model is now ready to update multiple records with varying values in a single query!
Let's take a look at some possible use cases for this new query:
Simple use case: Update the values of multiple records
Imagine that you have the following users table:
| id | name | username |
|---|---|---|
| 1 | Jorge Gonzales | iksaku |
| 2 | Gladys Martines | gm_mtz |
But, we want to update both records since those users have told us that their legal last name was misspelled:
Gonzálezis written with an accent on the lettera, and only usesz, never ans.Martínezis written with an accent on the letteri, and last letter should be az, not ans
Well, we can mass update those specific records:
User::massUpdate( values: [ ['id' => 1, 'name' => 'Jorge González'], ['id' => 2, 'name' => 'Gladys Martínez'], ] );
Now, both records will be updated with their corresponding values in a single query, resulting in:
| id | name | username |
|---|---|---|
| 1 | Jorge González | iksaku |
| 2 | Gladys Martínez | gm_mtz |
By default, the massUpdate query will grab your model's primary key name and apply it as part of
the query to not affect other records.
If you want to use another column as an index to separate value types, you could pass it as a second argument to the function call:
User::massUpdate( values: [ ['username' => 'iksaku', 'name' => 'Jorge González'], ['username' => 'gm_mtz', 'name' => 'Gladys Martínez'], ], uniqueBy: 'username' );
Simple use case #2: Updating multiple Eloquent Models
If you need to update the values in some Model classes and want to automatically mass update those changes, then this is for you!
The existing masUpdate query is capable of identifying the dirty attributes of Eloquent model classes
and compile them properly. You don't need to manually convert the models into an array, you just pass the
list of models you want to update, and it takes care of the rest.
Tip: If you pass a full list of
Eloquentmodels, only those with dirty values will be updated, so you don't actually need to filter the unchanged ones manually.
Let's recreate the previous example, but using Eloquent models...
// Say we already pulled our user models previously... Something like this: $jorge = User::where('name', 'Jorge Gonzales')->first(); $gladys = User::where('name', 'Gladys Martines')->first(); // And let's say we already made changes to those models... Like this: $jorge->name = 'Jorge González'; $gladys->name = 'Gladys Martínez'; // And now, let's update both models in a single query: User::massUpdate( values: [$jorge, $gladys] );
Pretty cool, right?
Note: It is only possible to mass update instances of the same
Eloquentmodel, it is not possible to mix the Query Builder with differentEloquentmodel classes.
Complicated use case: Using multiple indexes to differentiate records
Let's say that we just created expenses table to track how much we spend across time, and
we manually filled the following values:
| id | year | quarter | total_expenses |
|---|---|---|---|
| .. | .. | .. | .. |
| .. | 2019 | Q3 | 216.70 |
| .. | 2019 | Q4 | 216.70 |
| .. | 2020 | Q1 | 416.70 |
| .. | 2020 | Q2 | 211.12 |
| .. | 2020 | Q3 | 113.17 |
| .. | 2020 | Q4 | 422.89 |
| .. | 2021 | Q1 | 431.35 |
Above information is not real, I don't track my expenses quarterly.
Oops... We made a little mistake... Expenses from Q1 of 2020 and 2021 are switched, and in order to fix it
we could only pass the quarter column as an index, but if we only pass down the quarter column as an index,
we'll modify ALL Q1 records. So, for this, we should also pass down the year column as an index:
Expense::massUpdate( values: [ ['year' => 2020, 'quarter' => 'Q1', 'total_expenses' => 431.35], ['year' => 2021, 'quarter' => 'Q1', 'total_expenses' => 416.70], ], uniqueBy: ['year', 'quarter'] );
Tip: If you ever need to specify more than one or two indexes, just include all of them in the
valuesanduniqueByparameters.
The result in the table will be properly updated:
| id | year | quarter | total_expenses |
|---|---|---|---|
| .. | .. | .. | .. |
| .. | 2020 | Q1 | 431.35 |
| .. | .. | .. | .. |
| .. | 2021 | Q1 | 416.70 |
NOTE: It is important that you always include the
uniqueBycolumns in yourvaluesarray, exceptions will be thrown otherwise.
NOTE #2: It is not possible to update the values of the
uniqueBycolumns. Every column specified in this parameter will be filtered from the ones that are going to be updated.This prevents unexpected side effects from happening while updating
valuesinarrayshape and passed asEloquentmodels.
Advanced use case: Chaining with other query statements
Let's try to keep things simple and imagine a system that tracks To-Do items for multiple users:
| id | user_id | content | order |
|---|---|---|---|
| 1 | 1 | Pick up my daughter | 2 |
| 2 | 1 | Buy a new ThinkPad | 1 |
| 3 | 1 | Drink water | 3 |
Like every To-Do system, we let our users order their To-Do items to see the most important ones at
the top of the list, and to do this, we may be using a simple sorting package
that allows the user to drag items up and down the list.
Once the user moves one item in the list, in the backend we may receive an array with a specific key-value shape:
['position' => 'id']. With this, we're going to update the records' position based on the given id.
We can simply call our massUpdate query function and everything will be done... Well, sort of...
In this specific scenario, we're dealing with multiple lists for multiple users, that means that we may not
be always able to control which id columns are sent to the server, maybe some malicious actor wants to hijack
our To-Do list and lower the priority for buying ThinkPads. This is a pretty serious security concern.
There are many ways to solve this kind of issues, and a simple one is to chain query statements to our
massUpdate function.
In this case, we're going to add a where() statement to only update those items that belong to the currently
logged in user. And it's as simple as in any other Laravel query builder:
TodoItem::query() ->where('user_id', auth()->id()) ->massUpdate( values: collect($request->input('item_order')) ->mapWithKeys( fn ($id, int $position) => ['id' => $id, 'order' => $position] ) );
Tip: Did you know you can pass Collections, LazyCollections, Eloquent Collections and basically any
Arrayableinstance asvaluesto themassUpdatequery function?
This can be used as an extra layer to ensure data integrity when dealing with User-provided input that affects multiple records in the database.
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
If you discover any security related issues, please email yo@jorgeglz.io instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see License File for more information.
iksaku/laravel-mass-update 适用场景与选型建议
iksaku/laravel-mass-update 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 1.36M 次下载、GitHub Stars 达 137, 最近一次更新时间为 2021 年 06 月 28 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「laravel」 「iksaku」 「laravel-mass-update」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 iksaku/laravel-mass-update 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 iksaku/laravel-mass-update 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 iksaku/laravel-mass-update 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
This is my package laravel-swr-cache
Alfabank REST API integration
Laravel package for Accurate Online API integration.
Shared RCX Laravel DataTables UI and configuration helpers.
Boot a Laravel project on any machine with one command: app:serve installs missing tools (PHP, Node, Composer, Herd, Docker), creates .env, sets up the database, runs migrations, builds assets, starts a queue worker and serves via Herd, Sail or artisan serve; app:down cleanly stops everything it sta
Branded, diagnostic error pages (500, 403, 404, 419, 503) for Filament — native Filament UI, dark mode and translations out of the box.
统计信息
- 总下载量: 1.36M
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 137
- 点击次数: 18
- 依赖项目数: 2
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2021-06-28