Extend Blueprint class?

2020-05-31 12:04发布

I want to override the timestamps() function found in the Blueprint class. How can I do that?

e.g.,

public function up() {
    Schema::create('users', function (Blueprint $table) {
        $table->increments('id');
        $table->string('username')->unique();
        $table->string('password');
        $table->string('email');
        $table->string('name');
        $table->timestamps(); // <-- I want this to call my method instead of the one found in the base Blueprint class
    });
}

3条回答
女痞
2楼-- · 2020-05-31 12:34

Just to add a few points to Marcel Gwerder's answer (which is already great):


(edit 2016-03-06)
A GitHub issue has been recently opened about this: #12539.

查看更多
Emotional °昔
3楼-- · 2020-05-31 12:40

There is a new blueprintResolver function which takes a callback function which then returns the Blueprint instance.

So create your custom Blueprint class like this:

class CustomBlueprint extends Illuminate\Database\Schema\Blueprint{

    public function timestamps() {
        //Your custom timestamp code. Any output is not shown on the console so don't expect anything
    }
}

And then call the blueprintResolver function where you return your CustomBlueprint instance.

public function up()
{
    $schema = DB::connection()->getSchemaBuilder();

    $schema->blueprintResolver(function($table, $callback) {
        return new CustomBlueprint($table, $callback);
    });

    $schema->create('users', function($table) {
        //Call your custom functions
    });
}

I'm not sure if creating a new schema instance with DB::connection()->getSchemaBuilder(); is state of the art but it works.

You could additionally override the Schema facade and add the custom blueprint by default.

查看更多
够拽才男人
4楼-- · 2020-05-31 12:47

Marcel Gwerder's answer was a life saver. Like some of the users commented there, I wondered if this could be done more automagically. My goal was similarly to overwrite the timestamps method. After some tinkering, this is what I ended up with which is working for me:

I created a file at app/Classes/Database/Blueprint.php:

<?php

namespace App\Classes\Database;


use Illuminate\Support\Facades\DB;
use Illuminate\Database\Schema\Blueprint as BaseBlueprint;

class Blueprint extends BaseBlueprint
{
    /**
     * Add automatic creation and update timestamps to the table.
     *
     * @param  int  $precision
     */
    public function timestamps($precision = 0): void
    {
        $this->timestamp('created_at', $precision)->default(DB::raw('CURRENT_TIMESTAMP'));
        $this->timestamp('updated_at', $precision)->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
    }
}

I created a file at app/Facades/Schema.php

<?php

namespace App\Facades;

use App\Classes\Database\Blueprint;
use Illuminate\Database\Schema\Builder;
use Illuminate\Support\Facades\Schema as BaseSchema;

class Schema extends BaseSchema
{
    /**
     * Get a schema builder instance for a connection.
     *
     * @param  string|null  $name
     * @return Builder
     */
    public static function connection($name): Builder
    {
        /** @var \Illuminate\Database\Schema\Builder $builder */
        $builder = static::$app['db']->connection($name)->getSchemaBuilder();
        $builder->blueprintResolver(static function($table, $callback) {
            return new Blueprint($table, $callback);
        });
        return $builder;
    }

    /**
     * Get a schema builder instance for the default connection.
     *
     * @return Builder
     */
    protected static function getFacadeAccessor(): Builder
    {
        /** @var \Illuminate\Database\Schema\Builder $builder */
        $builder = static::$app['db']->connection()->getSchemaBuilder();
        $builder->blueprintResolver(static function($table, $callback) {
            return new Blueprint($table, $callback);
        });
        return $builder;
    }
}

Inside config/app.php I updated the alias for Schema as follows:

'aliases' => [
    'Schema' => App\Facades\Schema::class,
],

Now, in my migrations, like the below, when I call timestamps(), it calls my overwritten method.

<?php

use App\Classes\Database\Blueprint;
use \Illuminate\Database\Migrations\Migration;

class TimestampTest extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     * @throws \Throwable
     */
    public function up(): void
    {
        Schema::connection('mysql')->create('some_table', static function (Blueprint $table) {
            $table->string('some_column')->nullable();
            $table->timestamps();
        });

    }

    // ....
}
查看更多
登录 后发表回答