Расширить класс Blueprint?
Я хочу переопределить функцию timestamps()
, найденную в классе Blueprint
. Как я могу это сделать?
например.
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
Существует новая функция blueprintResolver
, которая принимает функцию обратного вызова, которая затем возвращает экземпляр Blueprint
.
Создайте свой собственный класс Blueprint следующим образом:
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
}
}
И затем вызовите функцию blueprintResolver
, где вы вернете экземпляр CustomBlueprint
.
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
});
}
Я не уверен, что создание нового экземпляра схемы с DB::connection()->getSchemaBuilder();
является современным, но оно работает.
Вы можете дополнительно переопределить фасад Schema
и по умолчанию добавить пользовательский проект.
Ответ 2
Просто добавьте несколько моментов к ответу Марселя Гвердера (что уже отлично):
-
Вы можете сократить DB::connection()->getSchemaBuilder()
до DB::getSchemaBuilder()
, потому что Laravel автоматически перенаправляет вызов метода на экземпляр соединения.
-
Каждый вызов Schema
Facade уже создает новый экземпляр Schema\Builder
, как показано в методе getFacadeAccessor()
в следующих файлах:
(edit 2016-03-06)
Недавно была открыта проблема GitHub: # 12539.
Ответ 3
Ответ марселя Гвердера был спасителем жизни. Как прокомментировали некоторые пользователи, я подумал, можно ли сделать это более автоматически. Моей целью было также переписать метод timestamps
. После некоторого возни, вот что я закончил, и это работает для меня:
Я создал файл в 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'));
}
}
Я создал файл в 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;
}
}
Внутри config/app.php
я обновил псевдоним для Схемы следующим образом:
'aliases' => [
'Schema' => App\Facades\Schema::class,
],
Теперь, в моих миграциях, как показано ниже, когда я вызываю timestamps()
, он вызывает мой перезаписанный метод.
<?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();
});
}
// ....
}