Morten Hagh
Morten Hagh

Reputation: 2113

Use middleware errorhandling with Slim 3

I am trying to use a custom error handler thingy on my small application using Slim 3 Framework.

I have made an error class that I want to use to output json with an error message and send a mail with the error description.

namespace App\Handlers;

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;

class CustomErrorHandlerMiddleware
{

    const MAIL = "[email protected]";

    public function __construct($message = "", $errorCode = null) {

        $this->message = $message;
        $this->code = ($errorCode != null) ? $errorCode : 500;
        $this->MailError();

    }

    public function __invoke(Request $request, Response $response, $next, $msg)
    {
        $errorArray = ["status" => "error", "message" => $this->message];

        $response->withStatus($this->code)->withHeader('Content-Type','application/json')->write(json_encode($errorArray));

        $response = $next($request, $response);

        return $response;
    }

    public function MailError() {

        $headers = 'From: [email protected]' . "\r\n" .
    'Reply-To: [email protected]' . "\r\n" .
    'X-Mailer: PHP/' . phpversion();

        $body = "Error:\n";
        $body .= $this->message."\n\n";

        try {
           mail(self::MAIL, "Error on localdashboards", $body, $headers);

        } catch(Exception $e) {
            echo $e->getMessage();
        }

    }

}

I might be doing this completely wrong, but is it possible to call this within another class, when a specific error occurs?

I am trying something like this:

   $delete = $this->db->database->delete("msn_ad_data", ["campaign_name" => $facebookData[0]["campaign_name"]]);

    if($delete) {

      $this->db->database->insert('msn_ad_data', [
            "campaign_id" => $facebookData[0]["campaign_id"],
            "campaign_name" => $facebookData[0]["campaign_name"],
            "impressions" => $facebookData[0]["impressions"],
            "status" => $facebookData[1]["status"],
            "pagename" => $facebookData[1]["bankarea"],
            "type" => $facebookData[1]["platform"]
       ]);

   } else {
       $this->app->add(new \App\Handlers\CustomErrorHandlerMiddleware("Could not save data"));
   }´

But it doesn't seem to work.

Basically I want to send a response with JSON, which I can output in the browser, that looks like

 [{
    "status": "error",
    "message": "Could not save data"
}]

and also send an email to me with the same response.

Upvotes: 1

Views: 1069

Answers (1)

jmattheis
jmattheis

Reputation: 11125

Middleware is not the correct thing to use here. You should just send the mail else or throw an exception and handle it in the errorHandler of slim:

} else {
    throw new CustomException("Could not save data");
}

Then add a custom errorHandler

$c = new \Slim\Container();
$c['errorHandler'] = function ($c) {
    return function ($request, $response, $exception) use ($c) {
        if($exception instanceof CustomException) {
            $message = $exception->getMessage(); // "could not save"
            $errorCode = //$exception->getErrorCode(); when you want todo this add this as method to the exception.
            // send mail
            $errorArray = ["status" => "error", "message" => $message];

            return $response->withStatus($errorCode)->withHeader('Content-Type','application/json')->write(json_encode($errorArray));

        }
        return $c['response']->withStatus(500)
                             ->withHeader('Content-Type', 'text/html')
                             ->write('Something went wrong!');
    };
};
$app = new \Slim\App($c);

You need the exception as well:

class CustomException extends \Exception {}

Upvotes: 2

Related Questions