placebook / framework-selfupdate
与 SQL 迁移的半自动工作
Requires
- php: ^7.1|^8.0
- ext-json: *
README
此包旨在对项目核心或第三方包的数据库结构进行半自动更新。
此包是 Placebook\Framework 的一部分,但可以用于您的任何项目。此外,它不仅可以用于 SQL 迁移,还可以用于任何其他可逆迁移。
内核工作方式
该项目包含一个用于此包的文件夹。例如,/install。此文件夹的路径已传递给包
use Placebook\Framework\Core\Install\SelfUpdate; SelfUpdate::$installDir = ROOT . '/install';
此目录包含 versions.json 文件和 custom_versions.json,内容如下
{ "details": { "0": {"class": null}, "1.0.0": {"class": "Migration_1"}, "2.0.0": {"class": "Migration_2"}, "3.0.0": {"class": "Migration_3", "namespace": "\\YourProject\\Test\\Migration"} } }
这里是版本描述。默认情况下,类名位于命名空间 Placebook\Framework\Core\Install 中,但可以指定另一个命名空间。内核版本将始终只增加第一个版本号,并在 versions.json 中。然后特定站点可以采用内核的当前版本,例如,3.0.0,并按您的喜好增加版本,但不能增加主版本号(3)。并将您的版本存储在文件 custom_versions.json 中。包将合并这两个文件,并能够从零开始升级到内核的最大版本,然后到特定项目的最大版本。同时,已经运行并具有自己的迁移的特定项目将能够更新其内核版本,并且与其一起更新的将是 versions.json。例如,将出现版本 4.0.0。然后包将更新内核,然后项目必须为其迁移分配版本 >4.0.0。Placebook\Framework 核心不会将版本保存到文件 custom_versions.json 中,它只属于您。这样,包将很好地与内核和项目迁移自动协同工作。
更新过程
指定的文件夹包含文件 db_version.lock。它存储内核的当前版本。如果没有文件,则版本解释为 0
在同一文件夹中有一个文件 updating.lock。如果存在,则更新正在进行中,则包将不会在另一个线程中启动更新。因此,如果迁移需要很长时间,则只有第一个请求(在上传新文件后)将启动迁移。其余的传入请求将基于基础结构进行处理。包读取所有可用的版本,并将它们按升序排列。从一个版本到另一个版本,需要经过所有中间版本。如果更新中断,则 updating.lock 文件将保留,并且更新不会再次启动,直到您手动解决问题。
对于站点
内核更新
namespace Placebook\Framework\Core\Install; SelfUpdate::$installDir = ROOT . '/install'; SelfUpdate::updateDbIfLessThen('6.0.0'); // update to a specific version SelfUpdate::updateDbIfLessThen(SelfUpdate::getMaxVersion()); // upgrade to maximum version // updateDbIfLessThen updates only upwards. If you need to roll back down, there is another method for this: $current = SelfUpdate::getDbVersion(); SelfUpdate::updateFromTo($current, '0.0.7'); // update that will work up and down (downgrade)
添加迁移
- 站点需要将迁移包装在一个实现了接口 Placebook\Framework\Core\Install\MigrationInterface 的类中
- 您需要在 custom_versions.json 中添加新版本下的类名和命名空间(如果它不是默认的 Placebook\Framework\Core\Install,则不是默认的)
- 在类中,最好实现向上迁移和迁移回滚
迁移类示例
<?php namespace Placebook\Framework\Core\Install; use Exception; use cri2net\php_pdo_db\PDO_DB; class Migration_sample implements MigrationInterface { public static function up() { $pdo = PDO_DB::getPDO(); try { $pdo->beginTransaction(); // something useful $pdo->commit(); } catch (Exception $e) { $pdo->rollBack(); throw $e; } } public static function down() { $pdo = PDO_DB::getPDO(); try { $pdo->beginTransaction(); // Rollback update $pdo->commit(); } catch (Exception $e) { $pdo->rollBack(); throw $e; } } }
对于包
只需要一个版本文件,不需要 custom_versions.json。建议的结构如下
- /vendor/vendor_name/package_name/versions.json
- /vendor/vendor_name/package_name/**/ 任何有用的类,包括具有迁移的类
由于网站上有模块,您可以将 SelfUpdate 的工作移入一个单独的文件,该文件将为所有请求连接。建议内容
<?php namespace Placebook\Framework\Core\Install; use Exception; // kernel update SelfUpdate::$installDir = PROTECTED_DIR . '/install'; // data about modules for updating $modules = [ ['vendor' => 'vendor1', 'name' => 'package1'], ['vendor' => 'vendor2', 'name' => 'package2'], ]; try { foreach ($modules as $module) { try { $versionsDir = PROTECTED_DIR . "/vendor/{$module['vendor']}/" . $module['name']; // path to vendor folder $versions = SelfUpdate::getVersions($versionsDir); // get package versions $max = SelfUpdate::getMaxVersion($versions); // get max version SelfUpdate::updatePackage($max, $versionsDir, $module['vendor'], $module['name']); // update } catch (Exception $e) { } } SelfUpdate::updateDbIfLessThen(SelfUpdate::getMaxVersion()); } catch (Exception $e) { }
已安装的模块版本将存储在路径 install/modules/<vendor_name>/<package_name>.version.lock 中。如果一个模块有数据库迁移并且可以通过 composer 安装,那么在将该项目作为依赖项添加时,只需将其添加到模块数组中一次,然后就可以通过 composer 更新其版本,数据库结构的更改将自动发生