我想在服务提供者中生成唯一的请求ID,请问这么写有问题吗?

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        define('REQUIRED_ID', (string) \Illuminate\Support\Str::uuid());
    }
}
让PHP再次伟大
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 18

没什么问题吧,有跨应用的需要吗,有就做一下“承上启下”

10个月前 评论
勇敢的心 (楼主) 10个月前

如果用octane的話 就有問題

10个月前 评论
勇敢的心 (楼主) 10个月前

能有什么问题?

10个月前 评论

这个不应该是前端请求的时候放在请求头里面吗

10个月前 评论
勇敢的心 (楼主) 10个月前

这个写日志官方不是给了你很好的示例吗 日志《Laravel 10 中文文档》

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Response;

class AssignRequestId
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        $requestId = (string) Str::uuid();

        Log::withContext([
            'request-id' => $requestId
        ]);

        return $next($request)->header('Request-Id', $requestId);
    }
}
10个月前 评论
勇敢的心 (楼主) 10个月前
sanders

和楼主不同,我们除了定时脚本都是常驻内存的,所以单独进行了封装,并通过监听器和基类方法重写的方式将数据存到各个地方,以便于跟踪。

<?php

namespace App\Services\Trace;

use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

/**
 * 生成跟踪数据
 */
class GenerateService
{
    /**
     * 生成跟踪数据
     *
     * @param string $referer
     * @return void
     */
    public function handle(string $referer): void
    {
        $id = Str::uuid()->toString();
        $this->handleById($id,$referer);
    }

    /**
     * 根据依赖注册的值还原跟踪数据并绑定日志
     *
     * @param string $id
     * @param string $referer
     * @return void
     */
    public function handleById(string $id, string $referer): void
    {
        $this->bind($id, $referer);
        Log::shareContext([
            config('trace.idName')  => $id,
            config('trace.referer') => $referer,
        ]);
    }

    /**
     * 绑定数据
     *
     * @param string $id 跟踪ID
     * @param string $referer 跟踪来源
     * @return void
     */
    public function bind(string $id, string $referer): void
    {
        app()->bind(config('trace.idName'), fn () => $id);
        app()->bind(config('trace.referer'), fn () => $referer);
    }

    /**
     * 解析数据
     *
     * @return array
     */
    public function resolveTraceData(): array
    {
        return  [
            config('trace.idName')  => app(config('trace.idName')),
            config('trace.referer') => app(config('trace.referer')),
        ];
    }
}

以上代码会根据 handle() 方法的调用将跟踪上下文混合到日志数据中去。

为了解决诸如请求出发队列这种问题,我们还将重写了 Illuminate\Queue\SerializesModels 的 __serialize() 方法 和 __unserialize() 方法,用来在队列中额外传递跟踪数据。

10个月前 评论
勇敢的心 (楼主) 10个月前

其实就是trace id的概念;不是强依赖唯一性,偶尔重复问题应该也不大;uuid 、雪花算法、 php自带的 uniqid; 我觉得都没问题;

不过在service provider里设置 trace id的地方是有待争议的;准确的来讲 trace id是跟随 request 产生的,你应该写在 index.php 里设置成request的属性


if (!$request->headers->has('X-TRACE-ID')) {
    $request->headers->set('X-TRACE-ID', genTraceId());
}

或者写一个 event listener, 监听request事件;在监听者里写上述代码;

10个月前 评论
FatTiger 10个月前
CodingHePing

只要不常驻内存就没毛病

10个月前 评论

如果是在我前几年经常加班的时候,这么写我是认为毫无问题的,因为代码能跑就好了。

现在我不会这样写了,define是定义常量,在计算机科学中常量意味着是不会改变的量。例如周二的数字形态是2 ,我会这样写。

            const Tuesday = 2;//or define(Tuesday,2);

我觉得不妥,是因为这是编码的基础。这里不是说在laravel中在php中这样使用不妥,而是编码不应该这样,尽管基于fpm架构下可以这样写。

但如果用常量来表示变量的写法让你获得了某些收益,也不是未尝不可。

10个月前 评论
勇敢的心 (楼主) 10个月前

应该在中间件中做,不应该在服务提供者中做,服务提供者是用来注册服务的

10个月前 评论
勇敢的心 (楼主) 10个月前

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