【问题标题】:What is the MySQL datatype SET equivalent in Laravel Schema?Laravel Schema 中的 MySQL 数据类型 SET 等价物是什么?
【发布时间】:2014-08-08 22:20:36
【问题描述】:

Laravel Schema 有一个与表等效的 ENUM 命令。什么是 SET 等价于表?

【问题讨论】:

    标签: php mysql database laravel schema


    【解决方案1】:

    到目前为止,Laravel Schema Builder 不支持列的 SET 数据类型。因此,在有人将这些代码添加到 Laravel 之前,这是一个替代解决方案。

    第 1 步:创建表,使用 ENUM 而不是 SET。

    Schema::create('schools', function($table)
    {
        $table->increments('id');
        $table->char('id_number', 6);
        $table->string('school_name');
        $table->enum('level', array('Preschool', 'Kindergarten', 'Primary', 'Secondary'))->index(); // *** fix this
        $table->string('phone');
        $table->string('email');
        $table->string('location');
        $table->smallInteger('city')->unsigned()->index();
        $table->smallInteger('country')->unsigned()->index();
        $table->smallInteger('head_teacher')->unsigned()->index();
        $table->smallInteger('director')->unsigned()->index();
        $table->smallInteger('created_by')->unsigned();
        $table->smallInteger('modified_by')->unsigned();
        $table->timestamps();
    });
    

    第 2 步:现在将 ENUM 更改为 SET。

    $table_prefix = DB::getTablePrefix();
    DB::statement("ALTER TABLE `" . $table_prefix . "schools` CHANGE `level` `level` SET('Preschool','Kindergarten','Primary','Secondary');");
    

    如果您有更好的解决方案,请告诉我。

    【讨论】:

    • 为什么不在之后添加表格(使用DB::statement 调用)?为什么要添加它,然后再更改它?
    • @ajon 好问题。我这样做是为了尽量减少DB::statement 的使用。
    【解决方案2】:

    第 1 步。 扩展默认类(将此代码添加到您的迁移文件中 use 部分之后):

    class ExtendedBlueprint extends Blueprint {
    
        /**
         * Create a new set column on the table.
         *
         * @param  string  $column
         * @param  array   $allowed
         * @return \Illuminate\Support\Fluent
         */
        public function set($column, array $allowed)
        {
            return $this->addColumn('set', $column, compact('allowed'));
        }
    
    }
    
    
    class ExtendedMySqlGrammar extends Illuminate\Database\Schema\Grammars\MySqlGrammar {
    
        /**
         * Create the column definition for an set type.
         *
         * @param  \Illuminate\Support\Fluent  $column
         * @return string
         */
        protected function typeSet(\Illuminate\Support\Fluent $column)
        {
            return "set('".implode("', '", $column->allowed)."')";
        }
    
    }
    

    第 2 步。 然后,我们需要将默认语法和蓝图类更改为我们的自定义:

    // set new grammar class
    DB::connection()->setSchemaGrammar(new ExtendedMySqlGrammar());
    
    // get custom schema object
    $schema = DB::connection()->getSchemaBuilder();
    
    // bind new blueprint class
    $schema->blueprintResolver(function($table, $callback) {
        return new ExtendedBlueprint($table, $callback);
    });
    
    // then create tables 
    $schema->create('table name', function(ExtendedBlueprint $table)
    {
        $table->increments('id');
        $table->text('sentence');
        $table->string('author')->nullable();
        $table->string('source')->nullable();
        $table->set('difficulty', range(1, 10)); // use our new mysql type 
        $table->boolean('enabled')->default(true);
    });
    

    这个方法在composer update之后也可以使用,因为我们没有编辑任何框架代码。

    【讨论】:

    • 执行此操作时出现错误。 Argument 1 passed to CreateTableName::{closure}() must be an instance of ExtendedBlueprint, instance of Illuminate\Database\Schema\Blueprint given 有什么想法吗?我确实在我的创建回调中将 Blueprint 更改为 ExtendedBlueprint。
    • 我想通了。我使用 Schema::create( ... ) 而不是 $schema->create( ... )
    【解决方案3】:

    Roman Nazarkin 的方法几乎可以完美运行,但是表前缀存在一个小问题(此方法不考虑),但是让这个建议适用于表前缀很简单:

    $grammar = DB::connection()->withTablePrefix(new ExtendedMySqlGrammar());
    // set new grammar class
    DB::connection()->setSchemaGrammar($grammar);
    
    // get custom schema object
    $schema = DB::connection()->getSchemaBuilder();
    
    // bind new blueprint class
    $schema->blueprintResolver(function($table, $callback) {
        return new ExtendedBlueprint($table, $callback);
    });
    
    // then create tables 
    $schema->create('table name', function(ExtendedBlueprint $table)
    {
        $table->increments('id');
        $table->text('sentence');
        $table->string('author')->nullable();
        $table->string('source')->nullable();
        $table->set('difficulty', range(1, 10)); // use our new mysql type 
        $table->boolean('enabled')->default(true);
    });
    

    【讨论】:

      【解决方案4】:

      扩展 laravel 数据库模式方法并不难。就像 Roman 写的那样,你也可以更新你的

      ,而不是扩展

      vendor/laravel/framework/src/Illuminate/Database/Schema/Grammers/MysqlGrammer.php

      /**
       * Create the column definition for an set type.
       *
       * @param  \Illuminate\Support\Fluent  $column
       * @return string
      */
      protected function typeSet(Fluent $column){
          return "set('".implode("', '", $column->allowed)."')";
      }

      vendor/laravel/framework/src/Illuminate/Database/Schema/Blueprint.php

      /**
           * Create a new set column on the table.
           *
           * @param  string  $column
           * @param  array   $allowed
           * @return \Illuminate\Support\Fluent
          */
          public function set($column, array $allowed){
              return $this->addColumn('set', $column, compact('allowed'));
          }

      在此之后,按 Ctrl + C 终止您的服务器。然后键入 php artisan serve 启动 laravel。

      【讨论】:

        【解决方案5】:

        当您需要创建自定义列而不创建其他文件来描述扩展语法时,我的简单一次性解决方案。在这里,我将自定义类型 rsvp_statuses 添加到 PostgresGrammar

            public function up()
            {
                DB::connection()->setSchemaGrammar(new class extends PostgresGrammar {
                    protected function typeRsvp_statuses(\Illuminate\Support\Fluent $column)
                    {
                        return 'rsvp_statuses';
                    }
                });
        
                Schema::create('mytable', function (Blueprint $table) {
                    $table->bigIncrements('id');
                    //...
                    $table->addColumn('rsvp_statuses', 'status');
                    $table->timestamps();
                });
            }
        

        【讨论】:

          【解决方案6】:

          Laravel 5.8 and onwards 在迁移中支持 SET 数据类型。对于最新版本,您只需使用 set() 函数:

          // SET equivalent column named flavors
          // Allowed values: strawberry , vanilla
          $table->set('flavors', ['strawberry', 'vanilla']);
          

          查看最新文档中的更多详细信息:

          【讨论】:

            猜你喜欢
            • 2011-03-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-06-24
            • 2013-03-23
            • 2010-10-20
            • 1970-01-01
            • 2010-09-12
            相关资源
            最近更新 更多