【问题标题】:Is there a way to create a citext field using Laravel 5 Migrations?有没有办法使用 Laravel 5 Migrations 创建一个 citext 字段?
【发布时间】:2015-07-27 16:10:45
【问题描述】:

具体来说,由于 MySQL 没有该字段类型,因此原始数据库查询似乎是个坏主意。由于 pgsql 默认缺少不区分大小写的文本字段,我们不得不使用这个扩展(当然,它工作得很好),但现在面临迁移的两难境地。

【问题讨论】:

    标签: php postgresql laravel laravel-5 laravel-migrations


    【解决方案1】:

    更新

    我创建了一个实现此功能的包。它为迁移添加了一个passthru() 方法,以便您可以创建任何您想要的字段类型。在本例中,安装包并添加服务提供者后,您只需在迁移文件中执行$table->passthru('citext', 'name');。这个包叫做“laravel-nomad”,可以在githubpackagist找到。


    是的,这是可以做到的。它需要扩展一些核心文件,但它是可行的。具体来说,您将需要一个新的连接、架构语法和蓝图。

    首先,在您的app 目录下创建一个新目录来保存您的自定义文件。例如,app/Extension。放置在此目录中的文件将扩展核心 Illuminate 文件,因此您将在此新目录下复制 Illuminate 文件夹结构。

    蓝图

    要添加可用于迁移的新方法,您需要更新蓝图。您将创建一个扩展核心蓝图类的自定义蓝图类。此自定义蓝图类将包含新方法(例如 ciText())。

    app/Extension/Database/Schema/PostgresCustomBlueprint.php

    <?php namespace App\Extension\Database\Schema;
    
    use Illuminate\Database\Schema\Blueprint;
    
    class PostgresCustomBlueprint extends Blueprint {
    
        /**
         * Create a new case-insensitive text column on the table.
         *
         * @param  string  $column
         * @return \Illuminate\Support\Fluent
         */
        public function ciText($column)
        {
            return $this->addColumn('ciText', $column);
        }
        
    }
    

    架构语法

    随着蓝图更新以允许ciText() 方法,您需要更新架构语法以能够处理ciText 字段。您将创建一个扩展核心 PostgresGrammar 模式语法类的自定义模式语法类。此自定义模式语法将具有将 Blueprint ciText 列转换为 citext 字段的方法。

    app/Extension/Database/Schema/Grammars/PostgresCustomGrammar.php

    <?php namespace App\Extension\Database\Schema\Grammars;
    
    use Illuminate\Database\Schema\Grammars\PostgresGrammar;
    use Illuminate\Support\Fluent;
    
    class PostgresCustomGrammar extends PostgresGrammar {
    
        /**
         * Create the column definition for a citext type.
         *
         * @param  \Illuminate\Support\Fluent  $column
         * @return string
         */
        protected function typeCiText(Fluent $column)
        {
            return 'citext';
        }
    
    }
    

    连接

    既然您有一个自定义蓝图和一个自定义架构语法,将允许使用 citext 字段,您需要创建一个自定义连接来使用这些新的自定义类。此自定义 Connection 类将扩展核心 PostgresConnection 类,以覆盖使用自定义模式语法和自定义蓝图所需的方法。

    app/Extension/Database/PostgresCustomConnection.php

    <?php namespace App\Extension\Database;
    
    use Illuminate\Database\PostgresConnection;
    use App\Extension\Database\Schema\Grammars\PostgresCustomGrammar as SchemaGrammar;
    use App\Extension\Database\Schema\PostgresCustomBlueprint;
    
    class PostgresCustomConnection extends PostgresConnection {
    
        /**
         * Get the default schema grammar instance.
         *
         * @return \App\Extension\Database\Schema\Grammars\PostgresCustomGrammar
         */
        protected function getDefaultSchemaGrammar()
        {
            return $this->withTablePrefix(new SchemaGrammar);
        }
    
        /**
         * Get a schema builder instance for the connection.
         *
         * @return \Illuminate\Database\Schema\Builder
         */
        public function getSchemaBuilder()
        {
            $parentBuilder = parent::getSchemaBuilder();
    
            // add a blueprint resolver closure that returns the custom blueprint
            $parentBuilder->blueprintResolver(function($table, $callback) {
                return new PostgresCustomBlueprint($table, $callback);
            });
    
            return $parentBuilder;
        }
    
    }
    

    服务提供者

    现在自定义连接已经设置好了,你需要告诉 Laravel 使用它。您可以覆盖内置的pgsql 驱动程序以使用PostgresCustomConnection 类,也可以为新连接创建一个新的驱动程序名称(例如pgsql-custom)。

    如果您只想覆盖内置的pgsql 驱动程序,则需要将以下行添加到您的app/Providers/AppServiceProvider.php 文件中的register() 方法中:

    $this->app->bind('db.connection.pgsql', 'App\Extension\Database\PostgresCustomConnection');
    

    如果您想创建一个新的驱动程序名称(例如pgsql-custom),您需要在register() 文件中的register() 方法中添加以下两行:

    $this->app->bind('db.connector.pgsql-custom', 'Illuminate\Database\Connectors\PostgresConnector');
    $this->app->bind('db.connection.pgsql-custom', 'App\Extension\Database\PostgresCustomConnection');
    

    数据库配置

    如果您创建一个新的驱动程序名称,请确保更新您的 config/database.php 文件,以将连接上的 driver 键的值设置为 pgsql-custom(或您为驱动程序命名的任何名称)。

    工匠

    最后,运行 artisan 命令以确保可以找到所有类并更新 app/Providers/AppServiceProvider 的任何缓存(编译)版本:

    composer dump-autoload
    php artisan clear-compiled
    php artisan optimize
    

    迁移

    现在您可以在迁移中使用ciText() 方法,它将创建一个citext 字段。

    <?php
    
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Database\Migrations\Migration;
    
    class CreateUsersTable extends Migration {
    
        /**
         * Run the migrations.
         *
         * @return void
         */
        public function up()
        {
            Schema::create('users', function(Blueprint $table)
            {
                $table->engine = 'InnoDB';
    
                $table->increments('id');
                $table->timestamps();
                $table->ciText('name');
                $table->ciText('email')->unique();
                $table->string('password', 60);
                $table->rememberToken();
            });
        }
    
        /**
         * Reverse the migrations.
         *
         * @return void
         */
        public function down()
        {
            Schema::drop('users');
        }
    }
    

    【讨论】:

    • 嗯,我当然希望它会更容易,但我会接受的。谢谢!
    • @CJThompson 我不知道您的编辑为什么被拒绝,但我修复了 dump-autoload 命令。感谢您了解这一点。
    • @CJThompson 我创建了一个包来执行此操作,并将信息添加到答案中。我确信您当前的项目正在进行中,但如果需要,我希望这对未来的项目有所帮助。
    • @EugenDimboiu 很高兴这对您有用。我现在实际上已经创建了一个包来处理这个问题,并将相关信息添加到答案中。我希望它可以帮助。
    • 只是想提一下,一年半之后,我们现在正在使用您的 passthru 包。再次感谢,完美运行
    猜你喜欢
    • 2013-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多