扩展Laravel 5.5/5.6 Blueprint

5
如何使用自定义方法$table->myMethod()扩展Laravel 5.5/5.6 MySQL Blueprint,类似于预构建的方法$table->timestamps();?
我已经尝试了一个SQLlite示例:Laravel 5中SQLite蓝图的扩展 ,但是我无法使其工作。我正在开发自己的软件包(使用软件包开发最佳实践),并希望从其中包括蓝图扩展。
我的开发软件包有 Laravel 扩展文件夹 "Extension": ./packages/vendorname/packagename/src/Extension/
有文件:
1) ./packages/vendorname/packagename/src/Extension/Blueprint.php
<?php

namespace Vendorname\Packagename\Extension;

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

class Blueprint extends ParentBlueprint
{

     public function myMethod()
     {
          $this->text('custom_column')->default('Some value');
          $this->text('custom_column2')->default('Some value2');
     }
}

2) ./packages/vendorname/packagename/src/Extension/MySqlConnection.php

2)./packages/vendorname/packagename/src/Extension/MySqlConnection.php
<?php

namespace Vendorname\Packagename\Extension;

use Vendorname\Packagename\Extension\Blueprint;
use Illuminate\Database\MySqlConnection as ParentMySqlConnection;
use Illuminate\Database\Schema\MySqlBuilder;

class MySqlConnection extends ParentMySqlConnection
{

     public function getSchemaBuilder()
     {
          if (is_null($this->schemaGrammar)) {
               $this->useDefaultSchemaGrammar();
          }

          $builder = new MySqlBuilder($this);
          $builder->blueprintResolver(function ($table, $callback) {
               return new Blueprint($table, $callback);
          });

          return $builder;
     }
}

我的包有服务提供者:./packages/vendorname/packagename/src/VendornamePackagenameServiceProvider.php,其中包含register()方法:

public function register()
{      if ($this->app->config->get('vendorname-packagename') === null) {
          $this->app->config->set('vendorname-packagename', require __DIR__.'/../config/vendorname-packagename');
     }

     $this->app->bind('db.connection.mysql', Vendorname\Packagename\Extension\MySqlConnection::class);
}

此外,我的软件包还有迁移文件:./packages/vanilla/vanilla-admin/src/migrations/2018_02_07_213437_create_logs_table.php

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
//use Vendorname\Packagename\Extension\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateLogsTable extends Migration
{

    public function up()
    {
        Schema::create('logs', function (Blueprint $table) {
            $table->increments('id');
            $table->text('package');
            $table->longText('log');
            $table->myMethod();
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('logs');
    }
}

我该如何在迁移中使用标准的"use Illuminate\Database\Schema\Blueprint;",因为我不想使用"use Vendorname\Packagename\Extension\Blueprint;"。另外,在运行迁移“php artisan migrate:refresh”时,我遇到了错误。
Type error: Argument 1 passed to CreateLogsTable::{closure}() must be a
  n instance of Vanilla\VanillaAdmin\Extension\Blueprint, instance of Ill
  uminate\Database\Schema\Blueprint given, called in /Users/raido/.compos
  er/vendor/bin/laravel-packages/vendor/laravel/framework/src/Illuminate/
  Database/Schema/Builder.php on line 164

请帮我找到解决方案。我在互联网上搜索并测试了一整天,但仍然无法使其正常工作 :(


请使用dc.connector.sqlite而不是db.connection.sqlite。 - DC-
请问有任何更新吗?我遇到了同样的问题。 - Malek Ben el ouafi
4个回答

5

当我搜索同样的问题时,我发现了这个。我正在使用Laravel 5.8并按照以下方式进行操作。

  1. 创建自定义Blueprint类
namespace App\Database\Schema;

class Blueprint extends \Illuminate\Database\Schema\Blueprint
{
    public function datetimeCreatedAt($precision = 0)
    {
        return $this->dateTime('created_at', $precision);
    }

}

创建MySqlConnection类或者其他你需要的类。
namespace App\Database;

class MySqlConnection extends \Illuminate\Database\MySqlConnection
{
    public function getSchemaBuilder()
    {
        $builder = parent::getSchemaBuilder();
        $builder->blueprintResolver(function ($table, $callback) {
            return new \App\Database\Schema\Blueprint($table, $callback);
        });

        return $builder;
    }
}
  1. 修改 AppServiceProvider
namespace App\Providers;

use App\Database\MySqlConnection;
use Illuminate\Database\Connection;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        Connection::resolverFor('mysql', function ($connection, $database, $prefix, $config) {
            return new MySqlConnection($connection, $database, $prefix, $config);
        });
    }
}

1
这绝对是2019年最好的答案。感谢您的贡献。 - Mandy Schoep

2

在 Laravel 5.5 中,扩展 Blueprint 的最佳方式是在您的 AppServiceProvider 引导方法中注册,如下所示:

Blueprint::macro('yourmethod', function () {  
    // your method here
});

1
我遇到了同样的问题,通过创建一个新的CustomBlueprint类来解决它。我在另一篇博客中写了详细内容。你可以去那里找到答案。 这里我只提供一个迁移文件示例,其中包含commonFields()方法,用于向模型添加通用字段。
    $schema = DB::connection()->getSchemaBuilder();

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

    $schema->create('roles', function (CustomBlueprint $table) {
        $table->bigIncrements('id');
        $table->string('name')->unique();
        $table->commonFields();
    });

我创建了CustomBlueprint类,其中包含该方法。
<?php
namespace App\common;
use Illuminate\Database\Schema\Blueprint;
class CustomBlueprint extends Blueprint
{
    public function commonFields()
    {
        $this->timestamp('created_at')->nullable();;
        $this->unsignedBigInteger('created_by')->nullable();
        $this->timestamp('updated_at')->nullable();;
        $this->unsignedBigInteger('updated_by')->nullable();
        $this->timestamp('deleted_at')->nullable();;
        $this->unsignedBigInteger('deleted_by')->nullable();
        $this->boolean('is_deleted')->default(0);
    }
}

链接: 在Laravel模式下自定义蓝图


我也必须测试一下 ;) - Raido Orumets

0

在迁移中只需要使用这个:

public function up()
{
    $schema = \DB::getSchemaBuilder();

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

    $schema->create('table_name', function (YourBlueprint $table) {
    ...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接