framework
framework copied to clipboard
[12.x] Introduce `Contextable`
Short summary
This is a simply way to create an object that syncs with the logging output.
Why? Dear god, why?
In a project I worked on semi-recently, we needed a "RequestContext" state that we stored. It was a class that was registered as a singleton in the container. A middleware would store the request data in the database, and then it would also keep a few other bits of data. Every time we updated the object via setters, it would re-sync itself to the Context facade.
In order to keep audit tracking, values from the request context was used in a number of inserts, hence why it was so meaningful to have it be a singleton.
Ok... maybe, but how do I use it.
It's pretty easy, just make yourself a Contextable object.
class RequestContext implements Contextable
{
public function __construct(
public ApiRequestModel $apiRequest,
public AuthType $authType
) {}
#[Override]
public function context($repository)
{
return [
'requesting_app' => $this->apiRequest->app_id,
'auth_type' => $this->authType->value,
'request_id' => $this->apiRequest->id,
];
}
}
// then in a middleware or whatever
$requestContext = new RequestContext(ApiRequestModel::capture($request), AuthType::BEARER_TOKEN);
app()->instance(RequestContext::class, $requestContext);
Context::add($requestContext);
// Then in my code, all of my logs will include the requesting_app, auth_type, and request_id data 😃
(Note: I fully expect Taylor to hate the idea of using an interface here, and instead we could just check that a method called contextData() exists on the Contextable. No problem)