zerifas / ladder
一个用PHP编写的数据库迁移工具。
Requires
- php: >=7.0
- pimple/pimple: ^3.0
- symfony/console: ^2.8
- symfony/event-dispatcher: ^2.8
- zerifas/collections: ^1.1
- zerifas/json: ^2.0
Requires (Dev)
- php-coveralls/php-coveralls: ^1.0
- phpunit/phpunit: ^6.5
- squizlabs/php_codesniffer: ^2.6
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(); } }