pmatseykanets/laravel-sql-migrations 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

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

pmatseykanets/laravel-sql-migrations

Composer 安装命令:

composer require pmatseykanets/laravel-sql-migrations

包简介

Raw SQL migrations for Laravel

README 文档

README

tests Total Downloads

Write your Laravel migrations in plain SQL.

If you find this package usefull, please consider bying me a coffee.

Buy Me a Coffee at ko-fi.com

Contents

Why

Don't get me wrong, the Laravel's SchemaBuilder is absolutely great and you can get a lot of millage out of it.

But there are cases when it's just standing in the way. Below are just a few examples where SchemaBuilder falls short.

Using additional / richer data types

I.e. if you're using PostgreSQL and you want to use a case insensitive data type for string/text data you may consider CITEXT. This means that we have to resort to a hack like this

class CreateUsersTable extends Migration
{
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->bigIncrement('id');
            $table->string('email')->unique();
            // ...
        });

        DB::unprepared('ALTER TABLE users ALTER COLUMN email TYPE CITEXT');
    }
}

instead of just

CREATE TABLE IF NOT EXISTS users (
    id BIGSERIAL PRIMARY KEY,
    email CITEXT UNIQUE,
    ...
);

Of course there are plenty of other data types (i.e. Range or Text Search data types in PostgreSQL) that might be very useful but SchemaBuilder is unaware of and never will be.

Managing stored functions, procedures and triggers

This is a big one, especially if you're still using reverse (down()) migrations. This means that you need to cram both new and old source code of a function/procedure/trigger in up() and down() methods of your migration file and keep them in string variables which doesn't help with readability/maintainability.

Even with heredoc / nowdoc syntax in php it's still gross.

Taking advantage of IF [NOT] EXISTS and alike

There is a multitude of important and useful SQL standard compliant and vendor specific clauses in DDL statements that can make your life so much easier. One of the well known and frequently used ones is IF [NOT] EXISTS.

Instead of letting ShemaBuilder doing a separate query(ies) to information_schema

if (! Schema::hasTable('users')) {
    // create the table
}

if (! Schema::hasColumn('users', 'notes')) {
    // create the column
}

you can just write it natively in one statement

CREATE TABLE IF NOT EXISTS users (id BIGSERIAL PRIMARY KEY, ...);
ALTER TABLE users ADD IF NOT EXISTS notes TEXT;

Using additional options when creating indexes

Some databases (i.e. PostgreSQL) allow you to (re)create indexes concurrently without locking your table.

CREATE INDEX CONCURRENTLY IF NOT EXISTS some_big_table_important_column_id 
    ON some_big_table (important_column);

CREATE INDEX IF NOT EXISTS table_json_column_idx USING GIN ON table (json_column);

You may need to create a specific type of index instead of a default btree

CREATE INDEX IF NOT EXISTS some_table_json_column_idx ON some_table (json_column) USING GIN;

Or create a partial/functional index

CREATE INDEX IF NOT EXISTS some_table_nullable_column_idx 
    ON some_table (nullable_column) 
    WHERE nullable_column IS NOT NULL;

Taking advantage of database native procedural code (i.e. PL/pgSQL)

When using PostgreSQL you can use an anonymous PL/pgSQL code block if you need to. I.e. dynamically (without knowing the database name ahead of time) set search_path if you want to install all extensions in a dedicated schema instead of polluting public.

The .up.sql migration could look like:

DO $$
BEGIN
  EXECUTE 'ALTER DATABASE ' || current_database() || ' SET search_path TO "$user",public,extensions';
END;
$$;

and the reverse .down.sql:

DO $$
BEGIN
  EXECUTE 'ALTER DATABASE ' || current_database() || ' SET search_path TO "$user",public';
END;
$$;

Installation

You can install the package via composer:

composer require pmatseykanets/laravel-sql-migrations

If you're using Laravel < 5.5 or if you have package auto-discovery turned off you have to manually register the service provider:

// config/app.php
'providers' => [
    ...
    SqlMigrations\SqlMigrationsServiceProvider::class,
],

Usage

Make SQL migrations

The most convenient way of creating SQL migrations is to use artisan make:migration with --sql option

php artisan make:migration create_users_table --sql

which will produce three files

database
└── migrations
    ├── 2018_06_15_000000_create_users_table.down.sql
    ├── 2018_06_15_000000_create_users_table.php
    └── 2018_06_15_000000_create_users_table.up.sql

I know, it bloats migrations directory with additional files but this approach allows you to mix and match traditional and plain SQL migrations easily. If it's any consolation if you don't use reverse (down) migrations you can just delete *.down.sql file(s).

Note: if you're creating files manually make sure that:

  1. The base php migration class extends SqlMigration class and doesn't contain up() and down() methods, unless you mean to override the default behavior.
  2. The filename (without extension) of .up.sql and .down.sql files matches exactly (including the timestamp part) the filename of the base php migration.

At this point you can forget about 2018_06_15_000000_create_users_table.php unless you want to configure or override behavior of this particular migration.

SqlMigration extends the built-in Migration so you can fine tune your migration in the same way

class CreateNextIdFunction extends SqlMigration
{
    // Use a non default connection
    public $connection = 'pgsql2';
    // Wrap migration in a transaction if the database suports transactional DDL
    public $withinTransaction = true;
}

Now go ahead open up *.sql files and write your migration code.

I.e. 2018_06_15_000000_create_users_table.up.sql might look along the lines of

CREATE TABLE IF NOT EXISTS users (
    id BIGSERIAL PRIMARY KEY,
    name CITEXT,
    email CITEXT,
    password TEXT,
    remember_token TEXT,
    created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

CREATE UNIQUE INDEX IF NOT EXISTS users_email_idx ON users (email);

and 2018_06_15_000000_create_users_table.down.sql

DROP TABLE IF EXISTS users;

You can also pass --sql option to make:model artisan command to instruct it to create plain SQL migrations for your newly created model.

php artisan make:model Post --migration --sql

Run SQL migrations

Proceed as usual using migrate, migrate:rollback and other built-in commands.

Example Projects

You can find bare Laravel 5.6 projects with default SQL migrations here:

Changelog

Please see CHANGELOG for more information about what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Credits

License

The MIT License (MIT). Please see License File for more information.

pmatseykanets/laravel-sql-migrations 适用场景与选型建议

pmatseykanets/laravel-sql-migrations 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 33.95k 次下载、GitHub Stars 达 34, 最近一次更新时间为 2018 年 06 月 17 日, 在 PHP 生态内属于活跃度较高的组件。

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

围绕 pmatseykanets/laravel-sql-migrations 我们能提供哪些服务?
定制开发 / 二次开发

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

BUG 修复 & 性能优化

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

项目外包 & 长期维护

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

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

统计信息

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

GitHub 信息

  • Stars: 34
  • Watchers: 3
  • Forks: 9
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2018-06-17