Extend Blueprint class?

陌路散爱 提交于 2019-12-04 15:59:17

问题


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
    });
}

回答1:


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.

For More Info, Please go through to this article.




回答2:


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

  • You can shorten DB::connection()->getSchemaBuilder() to DB::getSchemaBuilder() because Laravel automagically forward the method call to the connection instance.

  • Each call to the Schema Facade already creates a new Schema\Builder instance, as can be seen in the getFacadeAccessor() method in the following files:

    • Support/Facades/Schema.php - Laravel 4.2
    • Support/Facades/Schema.php - Laravel 5.0-dev


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




回答3:


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();
        });

    }

    // ....
}


来源:https://stackoverflow.com/questions/22444685/extend-blueprint-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!