zerifas/ladder

一个用PHP编写的数据库迁移工具。

v3.0.0 2018-12-27 16:37 UTC

This package is auto-updated.

Last update: 2024-09-05 02:50:07 UTC


README

这是什么?

Ladder 是一个数据库迁移系统,它的起源可以追溯到很多年前,最初是一个非常简单的系统。随着时间的推移,它增加了很多功能。它是为PHP >= 8.0编写的,并且通过PDO支持流行的MySQL数据库服务器。

我可以用这个做什么?

它可以与源代码控制(Git、Mercurial、SVN等)结合使用,以便跟踪数据库与应用程序源代码的更改。

这使得多个开发者可以同时在项目上工作,并知道他们是否拥有正确的数据库模式,以及他们可以通过一条命令将模式更新到最新版本。

迁移至少有两种方法:apply()rollback()。当迁移被应用时执行 apply() 方法,当它被取消应用时执行 rollback() 方法。逻辑上,rollback() 方法应该与它的对应方法 apply() 做相反的操作;删除列而不是添加它,等等。

支持什么?

  • 创建和删除表
  • 添加、删除和更改列
  • 添加和删除索引/约束
  • 数据操作:插入/更新/删除
  • 在应用迁移时存储元数据,并在回滚时使用它

如何使用它?

您可以使用Composer将Ladder添加到项目中

$ composer require zerifas/ladder
$ edit ladder.json

您的 ladder.json 文件应该类似于包含的 ladder.json.sample

{
    "db": {
        "host": "localhost",
        "dbname": "YOUR_DATABASE",
        "charset": "utf8",
        "username": "privileged_user",
        "password": "G00D_P@ssw0rd%"
    },
    "migrations": [
        {
            "namespace": "YourAppNamespace\\Migration",
            "path":      "src/Migration"
        }
    ]
}

如果您的数据库不存在,并且您的用户有权创建它,init 将会创建它

$ vendor/bin/ladder init
Created database 'test2'.

现在,您应该能够运行 status 命令来查看未应用的内容,并运行 migrate 来应用更改。

$ vendor/bin/ladder status
Status
    Missing Migrations
        1 - Ladder internal tables
$ vendor/bin/ladder migrate
Migrate from 0 to 1
Applying 1 - Ladder internal tables: OK

您可以让Ladder为您创建一个迁移模板文件

$ vendor/bin/ladder create 'Create user table'
src/Migration/Migration1455898526.php

模板显示了创建和删除一个表的示例,编辑并保存文件,然后

$ vendor/bin/ladder migrate
Migrate from 1 to 1455898526
Applying 1455898526 - Create user table: OK

此外,您还可以向 migrate 命令提供一个迁移ID,以便迁移到该特定点。

在提供 --rollback 选项的情况下,migrate 命令可以用来迁移到 较旧 的迁移。这是为了避免意外删除表或列。

命令

Ladder的目标是在使用时自我文档化(尽管我们需要迁移方法的文档)

$ vendor/bin/ladder
Ladder version 2.1.0

Usage:
  [options] command [arguments]

…

Available commands:
  create   Create a new Migration file.
  help     Displays help for a command
  init     Attempt to create the configured database.
  list     Lists commands
  migrate  Migrate to the latest, or specified migration number.
  reapply  Rollback the given migration (if applied), then apply it.
  remove   Rollback a single migration.
  status   Show the current status of the database.

示例迁移

这里有一个示例,它在一个迁移中做了 太多 的事情,但应该涵盖了所有用例。

<?php

namespace YourAppNamespace\Migration;

use Zerifas\Ladder\Migration\AbstractMigration;

class Migration1455898557 extends AbstractMigration
{
    public function getName()
    {
        return 'Demo lots of features';
    }

    public function apply()
    {
        // We are assuming that the `users` table already exists for this example,
        // and we are creating the `posts` table, and creating a user.
        $posts = $this->table('posts');

        // addColumn($name, $type, array $options = [])
        // Possible keys and values for `$options`:
        //     null - boolean used to allow a column's value to be null, default: true
        //     limit - integer for `varchar` column width, or string '10, 3' for `float`/`double` column precision
        //     options - array of strings for `enum` column options
        //     unsigned - boolean, used to mark `integer` columns as unsigned, default: false
        //     default - mixed value to use as default column value
        //     after - column name to add this new column after
        $posts->addColumn('id', 'autoincrement', ['null' => false, 'unsigned' => true])
            ->addColumn('userId', 'integer', ['null' => false, 'unsigned' => true])
            ->addColumn('urlSlug', 'varchar', ['null' => false, 'limit' => 10])
            ->addColumn('createdAt', 'datetime', ['null' => false])
            ->addColumn('publishedAt', 'datetime')
            ->addColumn('title', 'varchar', ['null' => false, 'limit' => 128])
            ->addColumn('body', 'text', ['null' => false])
            ->addIndex('PRIMARY', ['id']) // Create index named PRIMARY, containing the `id` column
            ->addIndex('userId') // If no columns given, Ladder assumes the name is a column
            ->addIndex('userId:createdAt', ['userId', 'createdAt'], ['unique' => true]) // Custom name, specified columns, and unique
            ->create()
        ;

        // Create a user, and get its unique id.
        $users = $this->table('users');
        $users
            ->addColumn('userGroup', 'integer', ['null' => false, 'default' => 0, 'first' => true])
            ->addColumn('notes', 'text', ['after' => 'userGroup'])
            ->alter()
        ;
        $users->insert([
            'username' => '<username here>',
            'password' => '<some valid password hash>',
        ]);

        // If we return an array from this `apply` method, the same data will be supplied
        // as the `$data` parameter when `rollback` is called.
        return [
            'userId' => $users->getLastInsertId(),
        ];
    }

    public function rollback(array $data = null)
    {
        $users = $this->table('users');

        if (($id = $data['userId'] ?? null)) {
            $users->delete([
                'id' => $id,
            ]);
        }

        $users
            ->dropColumn('notes')
            ->dropColumn('userGroup')
            ->alter()
        ;

        $this->table('posts')->drop();
    }
}