Morten Hagh Morten Hagh - 1 month ago 16
PHP Question

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 = "name@domain.com";

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: webmaster@example.com' . "\r\n" .
'Reply-To: webmaster@example.com' . "\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.

Answer

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 {}
Comments