我想覆盖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
});
}
答案 0 :(得分:13)
有一个新的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
外观并默认添加自定义蓝图。
答案 1 :(得分:3)
只是为Marcel Gwerder的答案添加几点(已经很棒了):
您可以将DB::connection()->getSchemaBuilder()
缩短为DB::getSchemaBuilder()
,因为Laravel会自动将方法调用转发给连接实例。
每次调用Schema
Facade都会创建一个新的Schema\Builder
实例,如以下文件中的getFacadeAccessor()
方法所示:
(编辑2016-03-06)
最近有一个GitHub问题:#12539。
答案 2 :(得分:1)
Marcel Gwerder的回答是挽救生命。就像一些用户在此处评论的那样,我想知道是否可以更自然地做到这一点。我的目标类似地是覆盖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
内部,我更新了Schema的别名,如下所示:
'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();
});
}
// ....
}