在Laravel的枢轴桌上的Uuid

问题描述 投票:1回答:1

我尝试执行laravel迁移来创建数据透视表。我有两个模型,它们被定义为多对多。以下是迁移方法

public function up() {
    Schema::create('api_user', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('api_id')->unsigned()->index();
        $table->foreign('api_id')->references('id')->on('apis')->onDelete('cascade');

        $table->uuid('user_uid')->unsigned()->index();
        $table->foreign('user_uid')->references('uid')->on('users')->onDelete('cascade');

        $table->timestamps();
    });
}

执行php artisan migrate后,我收到了sql错误

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'unsigned not null, `created_at` timestamp null, `updated_at` timestamp null) def' at line 1 (SQL: create table `api_user` (`id` int unsigned not null auto_increment primary key, `api_id` int unsigned not null, `user_uid` char(36) unsigned not null, `created_at` timestamp null, `updated_at` timestamp null) default character set utf8mb4 collate 'utf8mb4_unicode_ci')

Uuid在DB中存储为varch。也许varchart不能设置为unsigned属性。除了Laravel-5-Generators-Extended之外,从迁移创建数据透视表是另一种方法吗?

php mysql laravel laravel-5
1个回答
1
投票

这就是我做UUID的方式:

创建扩展蓝图

use Illuminate\Database\Schema\Blueprint;

class ExtendedBlueprint extends BluePrint{

    /**
     * Create a new uuid column on the table.
     *
     * @param  string  $column
     * @return \Illuminate\Support\Fluent
     */
    public function binary_uuid($column)
    {
        return $this->addColumn('buuid', $column);

    }
}

扩展您打算支持的所有语言的语法

use Illuminate\Database\Schema\Grammars\MySqlGrammar;
use Illuminate\Support\Fluent;


class MysqlExtendedGrammar extends MySqlGrammar 
{


    protected function typeBuuid(Fluent $column)
    {
        return "varbinary(16)";
    }

}

use Illuminate\Database\Schema\Grammars\PostgresGrammar;
use Illuminate\Support\Fluent;

class PostgesExtendedGrammar extends PostgresGrammar 
{


    protected function typeBuuid(Fluent $column)
    {
        return "uuid";
    }
}

use Illuminate\Support\Fluent;
use Illuminate\Database\Schema\Grammars\SQLiteGrammar;

use Illuminate\Database\Schema\Blueprint;

class SqlLiteExtendedGrammar extends SQLiteGrammar 
{

    protected function typeBuuid(Fluent $column)
    {
        return "blob";
    }
}

use Illuminate\Support\Fluent;
use Illuminate\Database\Schema\Grammars\SqlServerGrammar;
class SqlServerExtendedGrammar extends SqlServerGrammar 
{


    protected function typeBuuid(Fluent $column)
    {
        return "uniqueidentifer";
    }
}

然后创建一个架构提供程序

use Doctrine\Common\Proxy\Exception\UnexpectedValueException;
use Tschallacka\PageManager\Support\BluePrint\ExtendedBlueprint;
use Db;
use Event;

/**
 * Not so eloquent ;-)
 * @author tschallacka
 *
 */
class Stutter {

    private  $transforms = [
            'mysql'     => 'Tschallacka\PageManager\Support\Grammar\MysqlExtendedGrammar',
            'postgres'  => 'Tschallacka\PageManager\Support\Grammar\PostgesExtendedGrammar',
            'sqlite'    => 'Tschallacka\PageManager\Support\Grammar\SqlLiteExtendedGrammar',
            'sqlsrv'    => 'Tschallacka\PageManager\Support\Grammar\SqlServerExtendedGrammar',
    ];

    /**
     * Set the grammar to a certain driver
     * @param string $driver mysql, postgres, sqlite, sqlsrv, something else
     * @param string $grammar Your extended grammar class '\Foo\Bar\MysqlExtendedGrammar'
     */
    public function setGrammar($driver, $grammar) 
    {
        $this->transforms[$driver] = $grammar;  
    }

    public function getGrammar($driver) {
        if(array_key_exists($driver, $this->transforms)) {
            return $this->transforms[$driver];
        }
        throw new UnexpectedValueException("Unsupported database driver $driver\n"
                ."Please attach a listener to event tschallacka.get.binary_uuid.grammars\n"
                ."and provide an extended grammar for for generating 16 bit binary fields for UUIDs.\n"
                ."Take a look at /plugins/tschallacka/dynamicpages/support/MysqlExtendedGrammar.php");
    }

    public static function tableName($table_name) {
        $prefix = DB::connection()->getTablePrefix();
        return $prefix . $table_name;
    }
    public static function getExtendedSchema() 
    {
        $stutter = new static();
        Event::fire('tschallacka.get.binary_uuid.grammars',[$stutter]);
        $driver = DB::connection()->getConfig('driver');
        $grammar = $stutter->getGrammar($driver);

        DB::connection()->setSchemaGrammar(new $grammar());

        $schema = DB::connection()->getSchemaBuilder();
        $schema->blueprintResolver(function($table, $callback) {
            return new ExtendedBlueprint($table, $callback);
        });

        return $schema;
    }
}

然后在您的迁移文件中

class CreatePagesTable extends Migration
{
    public function up()
    {

        $schema = Stutter::getExtendedSchema();

        $schema->create(Stutter::tableName('pagemanager_pages'), 
            function(ExtendedBlueprint $table) {
                $table->engine = 'InnoDB';
                $table->increments('id');

                $table->binary_uuid('auid');

                $table->timestamps();
                $table->string('name')->nullable();
                $table->string('slug',2048)->nullable();
                $table->boolean('active')->nullable();

            });
    }

    public function down()
    {
        Schema::dropIfExists('tschallacka_pagemanager_pages');
    }
}

然后在您的模型中,您可以拥有以下属性:

protected function getAuidAttribute() 
{
    static $uuid;
    if(isset($this->attributes['auid'])) {
        if(is_null($uuid)) {
            $uuid = Uuid::import($this->attributes['auid']);
        }
        return $uuid->string;
    }

    return null;
}

protected function beforeCreate() 
{
    $uuid = Uuid::generate(4);
    $this->auid = $uuid->bytes;
    $this->attributes['auid'] = $uuid->bytes;
}

我正在使用的UUID库是https://github.com/webpatser/laravel-uuid

注意

我实际上使用的是Octobercms框架,它可能在一些小的实现细节上有所不同,但是大多数东西仍然应该支持laravel,因为OctoberCMS只是Laravel之上的一层。

© www.soinside.com 2019 - 2024. All rights reserved.