Проблема "невозможности" указать формат ответа у ошибок, которые, к примеру были вызваны вне контроллера и не могут быть "пропущены" через yii\filters\ContentNegotiator
имеет место быть, т.к. в сети по этому поводу 0, а в тех болванках, что предназначены для демонстрации возможностей Yii2 в плане REST из коробки, все решение данного вопроса сводилось к тому, чтобы просто явно указать формат ответа в yii\web\Response
, что вообще, я считаю, костыль, т.к. весь смысл отдачи ответа в разных форматах сразу продает.
Решение оказалось очень простым, просто нужно внимательно читать документацию к классам, а не бегать глазами по ней. В классе yii\filters\ContentNegotiator
черным по белому написано:
* The following code shows how you can use ContentNegotiator as a bootstrapping component. Note that in this case,
* the content negotiation applies to the whole application.
*
* // in application configuration
* use yii\web\Response;
*
* return [
* 'bootstrap' => [
* [
* 'class' => 'yii\filters\ContentNegotiator',
* 'formats' => [
* 'application/json' => Response::FORMAT_JSON,
* 'application/xml' => Response::FORMAT_XML,
* ],
* 'languages' => [
* 'en',
* 'de',
* ],
* ],
* ],
* ];
, что в переводе: "если тебе, парниш, нужен ровный, пацанский REST - пихай меня в boostrap своего приложения, и все будет шикарно". Именно так, нам и нужно сделать, но перед этим не забудьте убрать ContentNegotiator из списка поведений в контроллере.
Далее, есть еще такой момент. Дефолтный yii\web\ErrorHandler
, я считаю, нужно напильником немного. Данный ErrorHandler заменяет код ответа на 500, если исключение не имеет ничего общего с yii\web\HttpException
, т.е. экземпляром класса, но, и кроме этого, в случае запроса не указанного или неизвестного формата ответа кидается исключение yii\web\UnsupportedMediaTypeHttpException
, которое отдает ответ в HTML формата. Лично я "заглушил" контент ответа на это исключение и вернул только код ответа в заголовке, т.к. раз мы не знает такой формат, то и нечего что-то отдавать. Это все можно сделать так:
namespace app\components\rest;
use Yii;
use yii\web\Response;
use yii\web\UnsupportedMediaTypeHttpException;
/**
* @inheritdoc
*/
class ErrorHandler extends \yii\web\ErrorHandler
{
/**
* @inheridoc
*/
protected function renderException($exception)
{
if (Yii::$app->has('response')) {
$response = Yii::$app->getResponse();
// reset parameters of response to avoid interference with partially created response data
// in case the error occurred while sending the response.
$response->isSent = false;
$response->stream = null;
$response->data = null;
$response->content = null;
} else {
$response = new Response();
}
if ($exception instanceof UnsupportedMediaTypeHttpException) {
$response->data = '';
} else {
$response->data = $this->convertExceptionToArray($exception);
}
$response->setStatusCode($exception->statusCode);
$response->send();
}
}
Теперь все равно и по пацански. На районе оценят.