stfn / laravel-pending-updates
Requires
- php: ^8.1
- illuminate/contracts: ^9.0|^10.0
- spatie/laravel-package-tools: ^1.14.0
Requires (Dev)
- laravel/pint: ^1.0
- nunomaduro/collision: ^6.0
- nunomaduro/larastan: ^2.0.1
- orchestra/testbench: ^7.0|^8.0
- pestphp/pest: ^1.21
- pestphp/pest-plugin-laravel: ^1.1
- phpstan/extension-installer: ^1.1
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-phpunit: ^1.0
- phpunit/phpunit: ^9.5
- spatie/pest-plugin-test-time: ^1.1
README
When updating an Eloquent model, by using this package, you can postpone updating process for some time.
$news = News::find(1); $news->postpone() ->startFrom('2023-01-01 00:00:00') ->keepForHours(24) ->update(['is_active' => true]);
The model itself will not be updated in this case. The package will just schedule an update for you. So this news will be active only on 1st January for the whole day and after that, the package will revert the news to its previous state.
Installation
You can install the package via composer:
composer require stfn/laravel-pending-updates
You can publish and run the migrations with:
php artisan vendor:publish --tag="pending-updates-migrations"
php artisan migrate
You can publish the config file with:
php artisan vendor:publish --tag="pending-updates-config"
This is the contents of the published config file:
return [ // Maximum postpone in days. 'max_postpone_days' => 10, // The model uses to store pending updates. 'model' => \Stfn\PendingUpdates\Models\PendingUpdate::class, ];
When running the console command pending-updates:check
all pending updates will be checked
and if there is a need to revert some update to original table, this command will do that for you.
That command needs to be scheduled in the Laravel console kernel.
// app/Console/Kernel.php use Stfn\PendingUpdates\Commands\CheckPendingUpdates; protected function schedule(Schedule $schedule) { $schedule->command(CheckPendingUpdates::class)->everyMinute(); }
Usage
You should add the HasPendingUpdates trait to all models which need to have a pending update option.
use Illuminate\Database\Eloquent\Model; use Stfn\PendingUpdates\Models\Concerns\HasPendingUpdates; class Ticket extends Model { use HasPendingUpdates; }
With this in place, you will be able to postpone update of this model.
Using keep for
By using keep for, update will be performed at the moment, but package will revert changes after specific number of minutes, hours or days.
$ticket = Ticket::find(1); // Update ticket price to 200 and keep it updated for 60 minutes. $ticket->postpone() ->keepForMinutes(60) ->update(['price' => 200]); // Update ticket price to 200 and keep it updated for 12 hours. $ticket->postpone() ->keepForHours(12) ->update(['price' => 200]); // Update ticket price to 200 and keep it updated for 3 days. $ticket->postpone() ->keepForDays(3) ->update(['price' => 200]);
Using delay for
By using delay for, update will be performed later, after specific number of minutes, hours or days.
$ticket = Ticket::find(1); // Update ticket price to 200 after 60 minutes from now and keep it like that for unlimited time. $ticket->postpone() ->delayForMinutes(60) ->update(['price' => 200]); // Update ticket price to 200 after 12 hours from now and keep it like that for unlimited time. $ticket->postpone() ->delayForHours(12) ->update(['price' => 200]); // Update ticket price to 200 after 3 days from now and keep it like that for unlimited time. $ticket->postpone() ->delayForDays(3) ->update(['price' => 200]);
Using timestamps
You can also use timestamps to specify exact time when you want to update some model.
$product = Product::find(1); // Update product to be unavailable from 1st January. $product->postpone() ->startFrom("2023-01-01 00:00:00") ->update(['is_available' => false]); // Update product to be unavailable until 4th January. $product->postpone() ->revertAt("2023-04-01 00:00:00") ->update(['is_available' => false]); // Update product to be unavailable from 1st January to 4th January. $product->postpone() ->startFrom("2023-01-01 00:00:00") ->revertAt("2023-04-01 00:00:00") ->update(['is_available' => false]);
Using combination
A combination of specific minutes, hours, or days with timestamps is also possible.
$product = Product::find(1); // Update product to be unavailable from 1st January and keep that state for 1 day. $product->postpone() ->startFrom("2023-01-01 00:00:00") ->keepForDays(1) ->update(['is_available' => false]); // Update product to became unavailable after 60 minutes from now and keep that state until 4th January. $product->postpone() ->delayForMinutes(60) ->revertAt("2023-04-01 00:00:00") ->update(['price' => 200]);
Using methods on the model
By default, all fillable attributes are allowed to be postponed, but you can change that by overriding
allowedPendingAttributes
method.
use Illuminate\Database\Eloquent\Model; use Stfn\PendingUpdates\Models\Concerns\HasPendingUpdates; class Ticket extends Model { use HasPendingUpdates; public function allowedPendingAttributes() { return ['price']; } }
Keep in mind that those fields also need to be fillable.
Sometimes scheduled update may fail, for various reasons.
By default, the package will send that exception to your configured external
report service like Sentry, Flare, or Bugsnag and after that,
the record from the pending_updates
table will be removed. If you want to change this behavior, you can
override the updateCannotBeApplied
method on the PendingUpdateModel
.
use Illuminate\Database\Eloquent\Model; use Stfn\PendingUpdates\Models\PendingUpdate; class CustomPendingUpdate extends PendingUpdate { public function updateCannotBeApplied($exception, $model) { // Your custom logic here } }
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Credits
License
The MIT License (MIT). Please see License File for more information.