kdabrow / time-machine
Laravel / Lumen 库,允许在数据库中更改日期
1.2.0
2024-05-02 14:22 UTC
Requires
- php: ^7.2|^8.0
- illuminate/database: 6.0 - 12.0
Requires (Dev)
- orchestra/testbench: 4.0 - 10.0
README
时间机器
此包允许在数据库数据中移动时间。它会自动选择存储日期时间的所有字段,并根据给定的时间段或特定日期移动它们,相对于当前值。请查看示例以获取更多详细信息。
动机
此包可能有助于在预生产环境中测试持续时间较长的进程。例如,生成客户发票。通常,发票是在30天期限内生成的。您可以将客户及其所有数据移动到以前的发票周期(30天前的过去),并有效地模拟整个发票周期,就像客户是在30天前创建的一样。
。
安装
首先安装主包
composer require kdabrow/time-machine
然后安装数据库驱动包
建议将这些包作为 --dev 依赖项安装。
使用方法
时间旅行者设置
首先创建 TimeTraveller。只有 Eloquent 模型可以是 TimeTraveller。基本配置如下所示
<?php use Kdabrow\TimeMachine\TimeTraveller; use App\Models\User; // provide model instance $traveller = new TimeTraveller(new User()); // or class name $traveller = new TimeTraveller(User::class);
修改查询
TimeMachine 默认选择与给定的 TimeTraveller 模型相关的所有行。您可以为查询提供条件以限制查询
<?php use Illuminate\Database\Eloquent\Builder; use App\Models\User; use App\Models\Group; use Kdabrow\TimeMachine\TimeTraveller; use Kdabrow\TimeMachine\Result; use Illuminate\Support\Arr; // Result contains all previously changed models from all TimeTravellers // For example move Users only from previously changed Group $traveller = new TimeTraveller( User::class, function(Builder $builder, Result $result) { if ($result->isSuccessful(Group::class)) { return $query->whereIn( 'group_id', $result->getSuccessful(Group::class)->pluck('id') ); } } );
附加列
可以向查询中添加附加列。
<?php use App\Models\User; use Kdabrow\TimeMachine\TimeTraveller; use Kdabrow\TimeMachine\Database\Column; use Kdabrow\TimeMachine\Result; use Illuminate\Database\Eloquent\Model; $traveller = new TimeTraveller(User::class); $traveller->alsoChange('date_of_creation'); // It's possible to provide callback and determine how given field should be changed // Column object has information about currently modified column // Model is selected instance of User // Result contains previously moved in time data // In this example only move if no errors appeared during previous time travels $traveller->alsoChange( 'date_of_creation', function($currentValue, Column $column, Model $model, Result $result) { if (count($result->getAllFailed())) { return $currentValue; } return null; } );
排除字段
有时需要排除一些通常会被选中的字段以进行更改。
<?php use App\Models\User; use Kdabrow\TimeMachine\TimeTraveller; $traveller = new TimeTraveller(User::class); $traveller->exclude('date_of_birth');
设置键
选择进行时间旅行的记录基于模型的键。您可以重写它。
<?php use App\Models\User; use Kdabrow\TimeMachine\TimeTraveller; $traveller = new TimeTraveller(User::class); $traveller->setKeys(['uuid']);
时间机器和移动方向
创建 TimeTravellers 后,创建 TimeMachine。
<?php use Kdabrow\TimeMachine\TimeMachine; $timeMachine = new TimeMachine(); // now add previously created TimeTravellers $timeMachine->take($traveller1); $timeMachine->take($traveller2); $timeMachine->take($traveller3);
回到过去
首先创建 DateChooser。这是有关时间段或日期的信息。
<?php use Kdabrow\TimeMachine\DateChooser; use Kdabrow\TimeMachine\Result; use DateInterval; // move by DateInterval $chooser = new DateChooser(new DateInterval("P1D")); // Move by 1 day // or move by some specific amount of seconds $chooser = new DateChooser(3600); // Move by 1 hour // Now set up direction and start travel /** @var Result $result */ $result = $timeMachine ->toPast($chooser) ->start();
走向未来
首先创建 DateChooser。这是有关时间段或日期的信息。
<?php use Kdabrow\TimeMachine\DateChooser; use Kdabrow\TimeMachine\Result; use DateInterval; // move by DateInterval $chooser = new DateChooser(new DateInterval("P1D")); // Move by 1 day // or move by some specific amount of seconds $chooser = new DateChooser(3600); // Move by 1 hour // Now set up direction and start travel /** @var Result $result */ $result = $timeMachine ->toFuture($chooser) ->start();
移动到特定日期
首先创建 DateChooser。这是有关时间段或日期的信息。
<?php use Kdabrow\TimeMachine\DateChooser; use Kdabrow\TimeMachine\Result; use DateTime; // put DateTimeInterface object $chooser = new DateChooser(new DateTime("2020-15-16 12:12:12")); // Move datetime columns to 2020-15-16 12:12:12 // or provide datetime string $chooser = new DateChooser("2020-15-16 12:12:12"); // Move to 2020-15-16 12:12:12 // Now set up direction and start travel /** @var Result $result */ $result = $timeMachine ->toDate($chooser) ->start();
示例
将客户、其付款和订单移动10天到过去
更改前后数据库结构
customers (更改前)
customers (更改后)
payments (更改前)
payments (更改后)
orders
orders
脚本
<?php use Kdabrow\TimeMachine\TimeTraveller; use Kdabrow\TimeMachine\Result; use Kdabrow\TimeMachine\TimeMachine; use App\Models\Customer; use App\Models\Payment; use App\Models\Order; use Illuminate\Support\Arr; $customerId = 100; $customerTraveller = new TimeTraveller( Customer::class, function(Builder $builder, Result $result) use ($customerId) { return $builder->where('id', '=', $customerId); } ); $customerTraveller->exclude('date_of_birth'); $paymentTraveller = new TimeTraveller( Payment::class, function(Builder $builder, Result $result) use ($customerId) { if ($result->isSuccessful(Customer::class)) { return $builder->whereIn( 'customer_id', $result->getSuccessful(Customer::class)->pluck('id') ); } } ); $orderTraveller = new TimeTraveller( Order::class, function(Builder $builder, Result $result) use ($customerId) { if ($result->isSuccessful(Payment::class)) { return $builder->whereIn( 'payment_id', $result->getSuccessful(Payment::class)->pluck('id') ); } } ); $timeMachine = new TimeMachine(); $result = $timeMachine ->take($customerTraveller) ->take($paymentTraveller) ->take($orderTraveller) ->toPast(new DateInterval("P10D")) ->start(); // Get instances that failed time travel $failed = $result->getAllFailed(); $sucessful = $result->getAllSuccessful();
测试
从 docker 容器中运行测试
docker-compose exec php vendor/bin/phpunit
或直接从您的机器上运行
vendor/bin/phpunit