定制 pinkcrab/perique-migration 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

pinkcrab/perique-migration

Composer 安装命令:

composer require pinkcrab/perique-migration

包简介

A module for the Perique Framework which makes use of the PinkCrab Table Builder and PinkCrab Migration libraries.

README 文档

README

logo

Perique - Migrations

A wrapper around various PinkCrab libraries which make it easier to run DB migrations from a plugin created using the Perique Framework.

Latest Stable Version Total Downloads Latest Unstable Version License PHP Version Require GitHub contributors GitHub issues WordPress 6.6 Test Suite [PHP8.0-8.4] WordPress 6.7 Test Suite [PHP8.0-8.4] WordPress 6.8 Test Suite [PHP8.0-8.4] WordPress 6.9 Test Suite [PHP8.0-8.4] codecov Scrutinizer Code Quality Maintainability

Why?

There already exists a WPDB Migrations system written by PinkCrab for use in any WordPress plugin or even theme. However working this into Perique required building a small little isolated workflow due to the nature of how the Perique Registration Process works and how WordPress handles plugin events such as Activation, Deactivation and Uninstalling.

So to make it more seamless adding Database Migrations to Perique, we have created this library to help.

Depends on

As mentioned this library acts more of a bridge for the following packages.

Setup

$ composer require pinkcrab/perique-migrations

Creation of Migrations

To create database migrations, the Migration abstract class must be extended.

Full Migration model references below Example Plugin

class Acme_Migration extends Migration {
    
    /**
     * Returns the name of the table.
     *
     * @required
     * @return string Table name
     */
    protected function table_name(): string {
        return 'acme_migration_sample_table';
    }

    /**
     * Defines the schema for the migration.
     *
     * @param Schema $schema_config
     * @return void
     */
    public function schema( Schema $schema_config ): void {
        $schema_config->column( 'id' )
            ->unsigned_int( 11 )
            ->auto_increment();
    
        $schema_config->column( 'user_ref' )
            ->text( 11 );
    
        $schema_config->column( 'thingy_ref' )
            ->int( 11 );
    
        $schema_config->index( 'id' )
            ->primary();
    }

    /**
     * Defines the data to be seeded.
     *
     * @param array<string, mixed> $seeds
     * @return array<string, mixed>
     */
    public function seed( array $seeds ): array {
        return [
            [
                'user_ref'   => 'ghjuyitjkuiy'
                'thingy_ref' => 1325546
            ],
            [
                'user_ref'   => 'eouroipewrjhiowe'
                'thingy_ref' => 897456
            ]
        ];
    }
}

Example of table using Perique App Config for table names.

class Use_Dependency_Migration extends Migration {
    protected $config;
    public function __construct( App_Config $config ) {
        $this->config = $config;
    }
    protected function table_name(): string {
        return $this->config->db_tables('from_app_config');
    }    
}

Create the Migrations service

The Perique Migrations Module requires the Plugin Life Cycle to be added to the Perique App. This is to ensure that the migrations are run at the correct time.

// @file plugin.php

// Boot the app as normal and create an instance of Plugin_State_Controller
$app = (new App_Factory())
    // setup the app as normal
    ->default_setup()

    // Ensure Plugin Life Cycle is added
    ->module(Perique_Plugin_Life_Cycle::class)
    
    // Add the Migrations module
    ->module(
        Perique_Migrations::class,
        function( Perique_Migrations $module ) {
            
            // Optional key
            $module->set_migration_log_key( 'acme_plugin_migrations' )
            
            // Add you migrations
            $module->add_migration(Acme_Migration::class)
            $module->add_migration(Some_Migration_With_Dependencies::class);
        }
    )   
    ->boot();

Migration Model

All models must extend from the ( abstract ) PinkCrab\Perique\Migration\Migration class

class DI_Migration extends Migration {

    /** Services used */
    protected Some_Service $some_service;
    protected App_Config $config;

    /** These would be injected automatically via Perique DI */
    public function __construct(Some_Service $some_service, App_Config $config){
        $this->some_service = $some_service;
        $this->config = $config;
    }

    /** Gets the table name from the App_Config (Perique Config) */
    protected function table_name(): string {
        return $this->config->db_tables('from_app_config');
    }  

    /**Defines the schema for the migration. */
    public function schema( Schema $schema_config ): void {
        $schema_config->column( 'id' )->unsigned_int( 11 )->auto_increment();
        $schema_config->index( 'id' )->primary();    
        $schema_config->column( 'user_ref' )->text( 11 );
        $schema_config->column( 'thingy_ref' )->int( 11 );
    }

    /**
     * Defines the data to be seeded. */
    public function seed( array $seeds ): array {
        return $this->some_service->seed_data();
    }

    /** Is this table dropped on deactivation (Defaults to false). */
    public function drop_on_deactivation(): bool {
        return false;
    }

    /** Drop table on uninstall. (Defaults to false). */
    public function drop_on_uninstall(): bool {
        return true;
    }

    /** Should this migration be seeded on activation. (Defaults to true). */
    public function seed_on_inital_activation(): bool {
        return true;
    }  
}

Methods

__construct(...$deps)

@param mixed ...$deps Injected via the DI Container

You can inject any dependencies you need, so long as they either be inferred by the Type or has the rules define in the DI Rules. See the di container docs for more details

table_name(): string

@return string
@required method

This should return the final name for the table. This can be defined as a string literal or via an injected dependency (such as 'App_Config')

/**
 * Returns the table name from the apps config.
 *
 * @return string
 */
protected function table_name(): string {
    return $this->config->db_tables('from_app_config');
}  

schema( Schema $schema_config ): void

@param PinkCrab\Table_Builder\Schema $schema
@return null @required method

This allows for the definition of the tables schema. Please see the WPDB Migration and WPDB Table Builder libraries for more details

/**
 * Defines the schema for the migration.
 *
 * @param Schema $schema
 * @return void
 */
public function schema( Schema $schema ): void{
    $schema->column('id')->unsigned_int(12)->auto_increment();
    // Define rest of schema
}

seed( array $seeds ): array

@param array<int, array<string, mixed>> $seeds
@return array<int, array<string, mixed>>

Returns the data used to populate the table with. Should be returned as an array or arrays with matching column (key) and value pairs.

/**
 * Defines the schema for the migration.
 *
 * @param array<int, array<string, mixed>> $seeds  
 * @return array<int, array<string, mixed>>
 */
public function seed( array $seeds ): array {
    return [
        ['columnA' => 'value1', 'columnB' => 1.11],
        ['columnA' => 'value2', 'columnB' => 2.22],
    ];
}

drop_on_deactivation(): bool

@return bool

Depending on the return value, the table can be dropped on deactivation. Defaults to FALSE

/**
 * Is this table dropped on deactivation (Defaults to false)
 * @return bool
 */
public function drop_on_deactivation(): bool {
    return true;
}

drop_on_uninstall(): bool

@return bool

Depending on the return value, the table can be dropped on uninstall. Defaults to FALSE

/**
 * Is this table dropped on uninstall (Defaults to false)
 * @return bool
 */
public function drop_on_uninstall(): bool {
    return true;
}

seed_on_inital_activation(): bool

@return bool

Depending on the return value, will populate tables with defined seeded data Defaults to TRUE

Tables are only seeded once, even in the event of a later update.

/**
 * Should this migration be seeded on activation. (Defaults to true)
 * @return bool
 */
public function seed_on_inital_activation(): bool {
    return true;
}

up(): void

@return void

Lifecycle hook fired on every activation, after the table has been upserted and before any seed data is inserted. Default implementation is a no-op — override it when you need to run custom SQL (for example an ALTER to add a column introduced by a newer plugin version) or any other post-upsert work.

Because up() fires on every activation rather than just first install, implementations MUST be idempotent. Guard your work so running it twice has no effect.

The canonical use case is shipping a new Migration class in a later plugin version whose job is to evolve a table owned by an earlier migration:

class Add_Email_To_Users_Migration extends Migration {

    protected function table_name(): string {
        return 'my_users'; // same table as the original migration
    }

    public function schema( Schema $schema_config ): void {
        // No-op schema: the original migration already defines the table.
    }

    public function up(): void {
        global $wpdb;

        // Idempotency guard: only add the column if it's not there yet.
        $has_email = $wpdb->get_var( $wpdb->prepare(
            'SELECT COUNT(*) FROM information_schema.COLUMNS
             WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s',
            DB_NAME, 'my_users', 'email'
        ) );

        if ( (int) $has_email === 0 ) {
            $wpdb->query( 'ALTER TABLE my_users ADD COLUMN email VARCHAR(255) NULL' );
        }
    }
}

down(): void

@return void

Lifecycle hook fired just before the migration's table is dropped by the Deactivation or Uninstall event handlers. Only called for migrations that are actually being dropped — i.e. drop_on_deactivation() or drop_on_uninstall() returned TRUE. Migrations that stay in place do not have down() called. Default implementation is a no-op — override it to perform custom teardown (export rows elsewhere, emit an audit hook, etc.) while the table still exists.

public function down(): void {
    // Called right before the table is dropped.
    // Use this for last-chance teardown while the table is still readable.
}

Change Log

  • 2.2.0 - Add up() and down() lifecycle hooks on Migration for post-upsert work and pre-drop teardown. Uninstall cleanup now wraps drop + log removal in try/finally so a stale migration log can't outlive a failed drop.
  • 2.1.1 - Updated dev dependencies. Migration_Exception now surfaces the underlying DI failure reason (closes #32).
  • 2.1.0 - Update dependencies to support Perique V2.1
  • 2.0.0 - Support for Perique V2.*
  • 1.0.0 - Initial Release (Supports Perique V1.2-1.4)
  • 0.1.1 - Update dependencies and GH Action pipelines.
  • 0.1.0 - Docs added, sample project created.
  • 0.1.0-rc2 - Now uses Perique Plugin Life Cycle 0.2 and removes unneeded files when used as a lib via gitattributes
  • 0.1.0-rc1 Inital BETA release.

pinkcrab/perique-migration 适用场景与选型建议

pinkcrab/perique-migration 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 2.08k 次下载、GitHub Stars 达 0, 最近一次更新时间为 2021 年 12 月 22 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 pinkcrab/perique-migration 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 pinkcrab/perique-migration 我们能提供哪些服务?
定制开发 / 二次开发

基于 pinkcrab/perique-migration 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 2.08k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 22
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2021-12-22