3

I want to redirect to a page (error.php, or maybe 404/406.php, whatever the error is) depending on the info in a form in my website. I managed to log an error like this:

if ($date > $curdate) {
    return $response
        ->withStatus(406)
        ->withHeader('Content-Type', 'text/html')
        ->write('You can\'t select dates in the future!');
}

How can I do it so it sends you to a page with that error in particular instead of logging/requesting it in the network tab?

Edit for further explanation: Right now I get this:

Request URL:http://raspberrypi/chartAPI/api/{id}/{date1}/{date2}
Request Method:POST
Status Code:406 Not Acceptable
Remote Address:192.168.0.80:80
Referrer Policy:no-referrer-when-downgrade

Which is almost working as intended. What I want to do is it send me to "http://raspberrypi/chartAPI/error/406" (for example), and display the contents in a file called 406.php (or error406.php or whatever you want to call it).

Edit2: I now managed todo something with this:

return $response->withRedirect("error.php");

But I get this:

Request URL:http://raspberrypi/chartAPI/api/{id}/{date1}/error.php
Request Method:GET
Status Code:405 Method Not Allowed

And slim throws this error:

Method not allowed. Must be one of: POST

Why is it removing {date2}? And why is it asking for a POST method?

Newwt
  • 491
  • 1
  • 5
  • 22
  • Possible duplicate of [Can't redirect with status](http://stackoverflow.com/questions/43006106/cant-redirect-with-status) – Mika Tuupola Apr 26 '17 at 05:26
  • @MikaTuupola I edited my question because the link you put didn't help. Thanks anyways though! – Newwt Apr 26 '17 at 06:59

2 Answers2

1

You can extend the class NotFound like this

<?php
namespace App\Action;

use Slim\Handlers\AbstractHandler; 
use Slim\Views\Twig; 
use Psr\Http\Message\ServerRequestInterface; 
use Psr\Http\Message\ResponseInterface;

class CustomErrorHandler extends AbstractHandler {

private $view;

public function __construct(Twig $view) { 
    $this->view = $view; 
}

public function __invoke(ServerRequestInterface $request, ResponseInterface $response) { 
    parent::__invoke($request, $response);
    $status = $response->getStatusCode();

    $this->view->render($response, $status . '.twig');

    return $response->withStatus($status);
}

With Slim v3, PSR-7 and middleware, everything above can be accomplished in a few lines of code:

// $c is the DI container of Slim
$app->add(function ($request, $response, $next) use ($c) {
// First execute anything else
$response = $next($request, $response);

// Have multiple if's for each status code or use a switch based on $response->getStatusCode()
if (404 === $response->getStatusCode()) {
    // A 404 should be invoked
    $handler = $c['customErrorHandler'];
    return $handler($request, $response);
}

// Any other request, pass on current response
return $response;

}

Hope this helps

Daniel Fanica
  • 433
  • 1
  • 4
  • 11
  • That's only for 404, though. I want to handle custom errors or give custom messages along with whatever error I throw. – Newwt Apr 25 '17 at 13:23
  • This looks much better, but how can I implement it in my code? Do I save it as a class and call it giving it the error code I want to throw? – Newwt Apr 25 '17 at 13:42
1

You could create your own exception handler for Slim and create an array of errors for the handler to parse. When you inject it in to your new Slim instance, it will handle any exception you throw.

Slim Error Handler Docs

$slimErrorHandler = new Slim\Container;

// exception handler
$slimErrorHandler['errorHandler'] = function() {
    return function($request,$response,$exception) {
        $exceptionMessage = $exception->getMessage();
        $json = (array)json_decode($exceptionMessage);
        $error = array(
            'message' => $json['message'],
            'code' => $exception->getCode(),
            'errors' => (array)$json['errors']
        );

        $view = new Slim\Views\Twig(__DIR__);
        return $view->render($response,'error.html',$error);
    };
};

// page not found handler
$slimErrorHandler['notFoundHandler'] = function () {
    return function ($request,$response) {
        return $response->write('Page not found!');
    };
};

$app = new Slim\App($slimErrorHandler);

$app->get('/',function($request,$response) {
    $error = array(
        'message' => "Errors were found:",
        'errors' => array(
            "email" => "Please enter a valid email",
            "date" => "You can't select dates in the future!"
        )
    );

    throw new Exception(json_encode($error),409);
});

$app->run();

Template:

<h1>Whoops!</h1>

<p>{{ code }} : {{ message }}</p>

<ul>
    {% for error in errors %}
        <li>{{ error }}</li>
    {% endfor %}
</ul>
Rob
  • 1,840
  • 2
  • 12
  • 19