问题
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()
toDB::getSchemaBuilder()
because Laravel automagically forward the method call to the connection instance.Each call to the
Schema
Facade already creates a newSchema\Builder
instance, as can be seen in thegetFacadeAccessor()
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