plank / 快照
快照 Laravel 模型
Requires
- php: ^8.2
- doctrine/dbal: ^3.6
- illuminate/contracts: ^10|^11
- plank/laravel-hush: ^1.0
- spatie/laravel-package-tools: ^1.14.0
Requires (Dev)
- laravel/pint: ^1.0
- nunomaduro/collision: ^8.1.1|^7.10.0
- orchestra/testbench: ^9.0.0|^8.22.0
- pestphp/pest: ^2.17
- pestphp/pest-plugin-arch: ^2.3.3
- pestphp/pest-plugin-laravel: ^2.2.0
- phpstan/extension-installer: ^1.1
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-phpunit: ^1.0
README
Laravel 快照
⚠️ 包处于积极开发中。请等待 v1.0.0 版本用于生产使用。⚠️
快照是一个 Laravel 扩展包,允许您通过复制数据库表及其内容来版本化应用程序的内容。每个快照都代表应用程序内容在特定时间点的可浏览版本。通过更改应用程序的激活版本,您可以在先前版本中查看应用程序的内容。
此包的主要目标是实现您内容的强大版本控制,但又不干扰您的操作。您应该能够在不更改现有代码库的情况下使用它。它应该易于安装和配置,并且易于使用。
目录
安装
您可以通过 composer 安装此包
composer require plank/snapshots
您可以使用包的安装命令来完成安装
php artisan snapshots:install
快速开始
安装完成后,要开始使用此包
- 将所有针对版本化内容的迁移扩展为
Plank\Snapshots\Migrations\SnapshotMigration
,而不是框架的Migration
类。 - 在这些迁移中,将
Illuminate\Database\Schema\Builder
的引用替换为$this->schema
或Plank\Snapshots\Facades\SnapshotSchema
以针对版本化内容。 - 将所有表示版本化内容的模型实现为
Plank\Snapshots\Contracts\Versioned
并使用Plank\Snapshots\Concerns\AsVersionedContent
特性。 - 将所有不版本化但与版本化内容有关系的模型使用
Plank\Snapshots\Concerns\InteractsWithVersionedContent
特性。 - 创建一个中间件,根据请求设置应用程序的激活版本。
中间件示例
<?php namespace App\Http\Middleware; use Closure; use Plank\Snapshots\Contracts\ManagesVersions; class SetActiveVersion { public function __construct( protected ManagesVersions $versions ) { } public function handle($request, Closure $next) { $version = $request->route('version'); if ($version = $this->versions->byNumber($version)) { $this->versions->setActive($version); } return $next($request); } }
现在,每次您创建新版本时,SnapshotDatabase
监听器将处理 VersionCreated
事件并运行所有版本化内容的迁移。它还将从表的先前版本复制内容到新版本。
配置
包的配置文件位于 config/snapshots.php
。如果在安装期间未发布配置文件,您可以使用以下命令发布配置文件
php artisan vendor:publish --provider="Plank\Snapshots\SnapshotsServiceProvider" --tag="config"
版本模型
model
选项是用于存储应用程序版本的应用程序模型的完全限定类名。默认值是 Plank\Snapshots\Models\Version
。提供的任何模型都必须实现 Plank\Snapshots\Contracts\Version
接口。
版本工厂
factory
选项是用于生成版本实例以用于测试和填充应用程序的模型工厂的完全限定类名。默认值是 Plank\Snapshots\Factories\VersionFactory
。
仓库
repository
选项是用于检索应用程序版本的仓库的完全限定类名。默认值是 Plank\Snapshots\Repository\VersionRepository
。提供的任何仓库都必须实现 Plank\Snapshots\Contracts\ManagesVersions
接口。
自动迁移
“auto_migrate”选项决定当创建新版本模型时,包是否自动为所有版本化内容创建新表。该包提供了默认实现Plank\Snapshots\Listeners\SnapshotDatabase
,但您可以提供自己的实现。
自动复制
“auto_copy”选项决定当创建新版本模型时,包是否自动将内容复制到新版本表中。
该包提供了默认实现Plank\Snapshots\Listeners\CopyTable
,数据在数据库级别复制。
该包还附带Plank\Snapshots\Listeners\CopyModels
,数据在模型级别复制。如果您在模型中有自定义逻辑需要在数据复制时运行,这很有用。
您也可以通过在配置文件中设置它来提供自己的实现。
用法
版本
契约和模型
快照通过Version
模型进行标识和访问。该模型由包创建,或可以通过创建实现Plank\Contracts\Version
合约的类并指定为配置文件中的model
来由用户覆盖。
在使用此包的应用程序中,通常应指定一个“活动”的Version
。活动Version
将修改数据库表,其中将查询版本化内容。
事件
Plank\Events\VersionCreated
- 在创建新版本模型后触发
- 该包将其挂钩以运行所有版本化迁移,但可以通过将
auto_migrate
设置为false
来禁用
仓库
ManagesVersions
接口是迁移器所需的最小Version
存储库接口。该包提供了一个实现此接口的VersionRepository
类,但可以通过创建实现Plank\Contracts\ManagesVersions
合约的类并在配置文件中指定为repository
来由用户覆盖。
存储库负责查询现有版本和管理活动版本。它不用于创建新版本,因为那超出了包的范围。
迁移
快照迁移
此包添加了一个SnapshotMigration
类,用于存放所有版本化内容的迁移。它允许SnapshotMigrator
知道需要运行所有版本的迁移。
要使用它,只需让迁移类扩展SnapshotMigration
而不是框架的Migration
类。
<?php use Plank\Snapshots\Facades\SnapshotSchema; use Plank\Snapshots\Migrations\SnapshotBlueprint; use Plank\Snapshots\Migrations\SnapshotMigration; return new class extends SnapshotMigration { public function up() { $this->schema->create('blocks', function (SnapshotBlueprint $table) { $table->id(); $table->unsignedBigInteger('page_id'); $table->string('name'); $table->morphs('blockable'); $table->timestamps(); $table->foreign('page_id')->references('id')->onSnapshot('pages'); }); } public function down() { SnapshotSchema::dropIfExists('blocks'); } }
您会注意到在SnapshotMigration
中,您有可用的$this->schema
,它是SnapshotSchemaBuilder
实例。它是框架的\Illuminate\Database\Schema\Builder
类的包装器。您也可以使用SnapshotSchema
外观,但您应仅在SnapshotMigration
中使用它。
SnapshotMigrations
允许您以熟悉的方式声明迁移,但底层将处理所有版本化。
您还会注意到SnapshotBlueprint
类。这种蓝图类型存在是为了允许您使用->onSnapshot()
方法定义来自版本化内容到版本化内容的外键。
限制
-
来自未版本化内容到版本化内容的关系的外键不能使用。这是因为存在多个表的版本,外键不知道要引用哪个版本。来自版本化内容到未版本化内容以及来自版本化内容到版本化内容的外键仍然可以使用。
-
需要注意的是,如果至少有一个相关模型是版本化的,则枢轴表也应进行版本化。这是因为枢轴表需要为相关模型的每个版本进行复制。
-
同样需要注意的是,如果您正在使用已版本化的自定义枢轴模型,则无法通过枢轴将未版本化的内容与未版本化的内容相关联。因此,在使用自定义多态枢轴模型时,请特别小心您要关联的内容。
快照迁移器
此包将用SnapshotMigrator
类替换框架的迁移器。迁移器扩展了框架的迁移器,其唯一目的是确保为您的版本化内容运行迁移,适用于您应用的每个版本。
例如,在运行传统Laravel应用程序的迁移后,您可能会有以下情况
php artisan migrate INFO Preparing database. Creating migration table ............................... 13ms DONE INFO Running migrations. 2023_09_25_000000_create_users_table ............................... 10ms DONE 2023_09_25_000001_create_roles_table ............................... 10ms DONE 2023_09_25_000002_create_pages_table ............................... 14ms DONE
然而,在使用快照的Laravel应用程序中,您在初始迁移后可能会有以下情况
php artisan migrate INFO Preparing database. Creating migration table ............................... 13ms DONE INFO Running migrations. 2023_09_25_000000_create_users_table ............................... 10ms DONE 2023_09_25_000001_create_roles_table ............................... 10ms DONE 2023_09_25_000002_create_pages_table ............................... 14ms DONE 2023_09_25_000002_create_versions_table ............................... 14ms DONE
当创建第一个Version
模型时,假设页面内容是版本化的,并且将auto_migrate
设置为true
,则包将重新运行您的2023_09_25_000002_create_pages_table
迁移,以用于新的Version
。
以下输出仅作为示例。迁移在后台运行,不会输出。
php artisan migrate INFO Running migrations. v1_0_0_2023_09_25_000000_create_pages_table ............................... 10ms DONE
最后,假设您添加了一个新的迁移2023_09_25_000003_add_slug_to_pages_table
以向pages
表添加slug
列,并在部署时运行迁移。
php artisan migrate INFO Running migrations. 2023_09_25_000003_add_slug_to_pages_table ............................... 10ms DONE v1_0_0_2023_09_25_000003_add_slug_to_pages_table ............................... 10ms DONE
迁移应用于您内容的所有版本,以实现版本间的一致性。
模型
版本化模型
此包提供了一个Plank\Snapshots\Contracts\Versioned
接口和一个AsVersionedContent
特性。对于应该进行版本化的模型,让它们实现Versioned
接口,并使用AsVersionedContent
特性。
此特性确保模型表的查询以活动版本的表前缀进行前缀。它还覆盖了枢轴关系,以使用版本化的枢轴表。
示例
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Plank\Snapshots\Concerns\AsVersionedContent; use Plank\Snapshots\Contracts\Versioned; class Page extends Model implements Versioned { use AsVersionedContent; }
未版本化模型
对于任何与版本化模型有关联的模型,您可以使用Plank\Snapshots\Concerns\InteractsWithVersionedContent
特性。此特性确保当通过枢轴关联版本化模型时,使用版本化的枢轴表。
示例
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Plank\Snapshots\Concerns\InteractsWithVersionedContent; class User extends Model { use InteractsWithVersionedContent; public function pages() { return $this->belongsToMany(Page::class); } }
贡献
有关详细信息,请参阅CONTRIBUTING。
致谢
许可
MIT许可证(MIT)。有关更多信息,请参阅许可证文件。
安全漏洞
如果您在siren中发现安全漏洞,请发送电子邮件至security@plank.co。所有安全漏洞都将得到及时处理。
关注我们!
Plank专注于具有影响力的解决方案,为我们的客户及其用户提供引人入胜的体验。我们致力于数字空间中的创新、包容性和可持续性。了解更多关于我们改善网络使命的信息。