问题
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?
回答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
回答2:
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>
来源:https://stackoverflow.com/questions/43611649/redirecting-with-error-on-slim-framework