HeadersAlreadySentException

Обсуждение документации второй версии фреймворка. Переводы Cookbook и авторские рецепты.
Ответить
Аватара пользователя
SiZE
Сообщения: 2813
Зарегистрирован: 2011.09.21, 12:39
Откуда: Perm
Контактная информация:

HeadersAlreadySentException

Сообщение SiZE »

Error: yii\web\HeadersAlreadySentException: Headers already sent

Жизненный цикл web приложения, под веб приложением мы понимаем классы из namespace yii\web\* и их наследников:
1. Принять запрос
2. Вызвать соответствующий контроллер и экшен
3. Вернуть результат выполнения экшена

Магия происходит в п.3. За возврат результата отвечает класс yii\web\Response. По умолчанию он сконфигурирован для выдачи yii\web\Response::FORMAT_HTML. В зависимости от формата, ответ обрабатывается соответствующим декоратором, по умолчанию для yii\web\Response::FORMAT_HTML это yii\web\HtmlResponseFormatter, который добавляет заголовок Content-type: text/html.

Соответственно если наш экшен выглядит так:

Код: Выделить всё

public function actionSome($id)
{
    header("Content-type: my-type");
    echo "Test";
    var_dump($id);
}
то мы получим исключение HeadersAlreadySentException. Тоже самое если мы в пустом РНР скрипте вызовем такую конструкцию:

Код: Выделить всё

// наше echo, print, var_dump и тп в экшене или еще хуже до него.
echo();
// заголовок добавленный через декоратор вызванный в yii\web\Response
header();

Варианты решения. Если вам не жить не быть надо что-то вывести прямо из экшена, добавьте exit в конце, чтобы прервать выполнение скрипта, это больше подходит когда надо что-то свардампить.

Код: Выделить всё

public function actionSome($id)
{
    header("Content-Type: my-type");
    echo "Test";
    var_dump($id); exit;
}

Рабочий вариант:

Код: Выделить всё

public function actionSome($id)
{
    $response = Yii::$app->response;
    $response->format = yii\web\Response::FORMAT_RAW;
    $response->getHeaders()
        ->set('Content-Type', "my-type");
        
    return 'test';
}
Ответить