[实战]laravel 利用trait实现中间件指定数据库按月份水平分表记录系统日志

创建模型以及迁移文件

php artisan make:model SystemTraceRecords -m
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateSystemTraceRecordsTable extends Migration
{
    protected $connection = 'xiongge_log';

    public function up()
    {
        Schema::create('system_trace_records', function (Blueprint $table) {
            $table->id();
            $table->foreignId('users_id')->index()->default(0)->comment('用户id');
            $table->json('data')->nullable()->comment('data');
            $table->string('method')->nullable()->comment('method');
            $table->string('secure')->nullable()->comment('secure');
            $table->string('path')->nullable()->comment('path');
            $table->string('uri')->nullable()->comment('uri');
            $table->string('response')->nullable()->comment('response');
            $table->string('status')->nullable()->comment('status');
            $table->timestamps();
        });
         \DB::statement("ALTER TABLE `xg_system_trace_records` comment '系统跟踪记录'");
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('system_trace_records');
    }
}

模型

<?php

namespace App\Models;

use App\Traits\SubmeterTraits;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use DateTimeInterface;


class SystemTraceRecords extends Model
{
    use HasFactory, SubmeterTraits;

    protected $connection = "xiongge_log";

    protected $guarded = [];

    protected $table = "system_trace_records";

    protected $primaryKey = 'id';

    protected $prefix = 'xg_';

    protected $casts = [
        'created_at' => 'datetime:Y-m-d H:i',
        'updated_at' => 'datetime:Y-m-d H:i',
    ];

    protected function serializeDate(DateTimeInterface $date)
    {
        return $date->format('Y-m-d H:i:s');
    }

    protected $columns;

    public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);
        // 初始化分表处理
        $this->init();
    }
}

trait

<?php

namespace App\Traits;

use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

trait SubmeterTraits
{
    //是否分表,默认false,即不分表
    protected $isSplitTable = true;

    //原表
    public $originTable;

    //表
    public $endTable;

    /**
     * 后缀参数
     * @var string
     */
    protected $suffix = null;

    /**
     * 年月参数:202104
     * @var string
     */
    public $ym;

    public function init(array $attributes = [], $suffix = null)
    {
        //默认原表
        $this->originTable = $this->table;
        //默认最终表
        $this->endTable = $this->table;

        $this->ym = Carbon::now()->format('Ym');

        //isSplitTable参数为true时进行分表,否则不分表
        if ($this->isSplitTable) {
            //初始化后缀,未传则默认年月分表
            $this->suffix = $suffix ?: $this->ym;
        }
        //初始化分表表名并创建
        $this->setSuffix();
    }

    /**
     * 设置表后缀, 如果设置分表后缀,可在service层调用生成自定义后缀表名,
     * 但每次操作表之前都需要调用该方法以保证数据表的准确性
     * @param $suffix
     */
    public function setSuffix($suffix = null)
    {
        //isSplitTable参数为true时进行分表,否则不分表
        if ($this->isSplitTable) {
            //初始化后缀,未传则默认年月分表
            $this->suffix = $suffix ?: $this->ym;
        }
        if ($this->suffix !== null) {
            //$this->endTable = $this->getTable() . '_' . $suffix;
            $this->endTable = $this->originTable . '_' . $this->suffix;

            //最终表替换模型中声明的表作为分表使用的表
            $this->table = $this->endTable;
        }
        //调用时,创建分表,格式为 table_{$suffix}
        //未传自定义后缀情况下,,默认按年月分表格式为:orders_202205
        //无论使用时是否自定义分表名,都会创建默认的分表,除非关闭该调用
        $this->createTable();
    }

    /**
     * 提供一个静态方法设置表后缀
     * @param string $suffix
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public static function suffix($suffix = null)
    {
        $instance = new static;
        $instance->setSuffix($suffix);
        return $instance->newQuery();
    }

    /**
     * 创建新的"table_{$suffix}"的模型实例并返回
     * @param array $attributes
     * @param bool $exists
     * @return object $model
     */
    public function newInstance($attributes = [], $exists = false)
    {
        $model = parent::newInstance($attributes, $exists);
        $model->setSuffix($this->suffix);
        return $model;
    }

    /**
     * 创建分表,没有则创建,有则不处理
     */
    protected function createTable()
    {
        info("createTable===============", [Schema::connection($this->connection)->hasTable($this->endTable)]);
        //初始化分表,,按年月分表格式为:orders_202205
        if (!Schema::connection($this->connection)->hasTable($this->endTable)) {
            info("创建表==========", [$this->endTable]);
            DB::connection($this->connection)->update("create table {$this->prefix}{$this->endTable} like {$this->prefix}{$this->originTable}");
        }
    }

}

创建中间件

php artisan make:middleware SystemTraceRecords
protected $routeMiddleware = [
    'systemTraceRecords' => \App\Http\Middleware\SystemTraceRecords::class,
];
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class SystemTraceRecords
{
    public function handle(Request $request, Closure $next)
    {
        $response = $next($request);
        if ($request->getMethod() != "POST") return $response;
        \App\Models\SystemTraceRecords::query()->create(
            [
                'users_id' => Auth::id() ?? 0,
                'data' => json_encode($request->all(), JSON_UNESCAPED_UNICODE),
                'method' => $request->getMethod(),
                'secure' => $request->getScheme(),
                'uri' => $request->getRequestUri(),
                'path' => $request->path(),
//            'response' => $response->getContent() ?: '',
                'status' => $response->getStatusCode()
            ]
        );
        return $response;
    }
}

结果

laravel 实现指定数据库按月份水平分表

相关文档

laravel 8实现 订单表按月份水平分表
PHP trait的使用和详解

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 16

分表后通过交易单号搜索订单,在多张表中怎么搜索这个数据

1年前 评论
my38778570 (楼主) 1年前
PHPer技术栈 (作者) 1年前
my38778570 (楼主) 1年前
PHPer技术栈 (作者) 1年前
my38778570 (楼主) 1年前
my38778570 (楼主) 1年前
my38778570 (楼主) 1年前
PHPer技术栈 (作者) 1年前
PHPer技术栈 (作者) 1年前
my38778570 (楼主) 1年前
PHPer技术栈 (作者) 1年前
my38778570 (楼主) 1年前
PHPer技术栈 (作者) 1年前
my38778570 (楼主) 1年前
my38778570 (楼主) 1年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!