[实战]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 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 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周前

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