Getting Request Attributes in Error Handler


#1

Hello Folks,

I’ve implemented Monolog on my Slim Application and I would to keep record of the Users whenever some Exception or Error occurs. ( Not only Users but some other data about the request that come from my Database ).

I have my Custom Error Handler that does all the formatting I need and trigger the logger. But I having trouble getting for example User data.

Currently there is a Middleware that retrieve user information and store it in Request Attributes.

Example: UserMiddleware

$newRequest = $request->withAttributes($userData);

$newResponse = $next($newRequest,$response);

and then on the next Route or Middleware I just have to: $request->getAttributes()['user'] and all my User data is there for use.

Lets say that UserMiddleware have completed its task without Error and moved to the Login Route and then something bad happened. That would lead to an Exception and it’ll be handler by errorHandler.

The thing is I cannot do the same in the Error Handler as its not the same $request object I think.

Example:

   $this->container['errorHandler'] = function (ContainerInterface $container) {
                return function (Request $request, Response $response, Exception $exception) use ($container) {
                      
                      // This return an Empty Array.
                      $requestAttr = $request->getAttributes();

                     // This isn't even possible.
                      $userData = $requestAttr['user];

         };
   };

EDITED:

Currently I’m passing the Attributes to the Container everytime that setAttributes is called so that in the Handler I can retrieve all type of data.

Example: On Controller

// Just an Example.
public function setRequestAttributes($data, $replace = false){
     $this->requestInstance = $this->requestInstance->withAttributes($data)
     $this->getInterfaceContainer('Attributes') = $this->requestInstance->getAttributes();
}

Example: On Handler

 $requestAttributes = $container->get('Attributes');

Is there any way better or safer to do that ? This is the only one I got.

Thanks,
LosLobos.


#2

If you take a look on this code you will see how Slim handle erros.
But talking about your problem, you can just inject the request/response on your Exception like Slim/Exception/MethodNotAllowedException (that extends SlimException) do.
Then you can do something like:

throw new MyException($request, $response, $anotherArgument, ...)

And on your error handler

$this->container['errorHandler'] = function (ContainerInterface $container) {
                return function (Request $request, Response $response, Exception $exception) use ($container) {
                     $requestAttr = $exception->getRequest()->getAttributes();
         };
   };

#3

This could be an approuch but the problem is that I dealing with multiple type of Exceptions. And if I filter the $exception using instanceof I’ll be excluding the other Exceptions and I’ll not be catching all the Errors. ( Exceptions, ArgumentInvalidExceptions, other type of exceptions… )

I think using the Container is the best idea at the moment when dealing with this situation.