Ответы ¶
Когда приложение заканчивает обработку запроса, оно генерирует объект ответа
и отправляет его пользователю. Объект ответа содержит такие данные, как HTTP-код состояния, HTTP-заголовки и тело ответа.
Конечная цель разработки Web-приложения состоит в создании объектов ответа на различные запросы.
В большинстве случаев вам придется иметь дело с компонентом приложения response
,
который по умолчанию является экземпляром класса yiiwebResponse. Однако Yii также позволяет вам создавать собственные
объекты ответа и отправлять их пользователям. Это будет рассмотрено ниже.
В данном разделе мы опишем, как составлять ответы и отправлять их пользователям.
Код состояния ¶
Первое, что вы делаете при построении ответа, — определяете, был ли успешно обработан запрос. Это реализуется заданием
свойству yiiwebResponse::$statusCode значения, которое может быть одним из валидных
HTTP-кодов состояния. Например, чтобы показать, что запрос был
успешно обработан, вы можете установить значение кода состояния равным 200:
Yii::$app->response->statusCode = 200;
Однако в большинстве случаев явная установка не требуется так как значение yiiwebResponse::$statusCode
по умолчанию равно 200. Если вам нужно показать, что запрос не удался, вы можете выбросить соответствующее
HTTP-исключение:
throw new yiiwebNotFoundHttpException;
Когда обработчик ошибок поймает исключение, он извлечёт код состояния
из исключения и назначит его ответу. Исключение yiiwebNotFoundHttpException в коде выше
представляет HTTP-код состояния 404. В Yii предопределены следующие HTTP-исключения:
- yiiwebBadRequestHttpException: код состояния 400.
- yiiwebConflictHttpException: код состояния 409.
- yiiwebForbiddenHttpException: код состояния 403.
- yiiwebGoneHttpException: код состояния 410.
- yiiwebMethodNotAllowedHttpException: код состояния 405.
- yiiwebNotAcceptableHttpException: код состояния 406.
- yiiwebNotFoundHttpException: код состояния 404.
- yiiwebServerErrorHttpException: код состояния 500.
- yiiwebTooManyRequestsHttpException: код состояния 429.
- yiiwebUnauthorizedHttpException: код состояния 401.
- yiiwebUnsupportedMediaTypeHttpException: код состояния 415.
Если в приведённом выше списке нет исключения, которое вы хотите выбросить, вы можете создать его, расширив класс
yiiwebHttpException, или выбросить его напрямую с кодом состояния, например:
throw new yiiwebHttpException(402);
Вы можете отправлять HTTP-заголовки, работая с коллекцией заголовков компонента response
:
$headers = Yii::$app->response->headers;
// добавить заголовок Pragma. Уже имеющиеся Pragma-заголовки НЕ будут перезаписаны.
$headers->add('Pragma', 'no-cache');
// установить заголовок Pragma. Любые уже имеющиеся Pragma-заголовки будут сброшены.
$headers->set('Pragma', 'no-cache');
// удалить заголовок (или заголовки) Pragma и вернуть их значения массивом
$values = $headers->remove('Pragma');
Информация: названия заголовков не чувствительны к регистру символов. Заново зарегистрированные заголовки не отсылаются
пользователю до вызова yiiwebResponse::send().
Тело ответа ¶
Большинство ответов должны иметь тело, содержащее то, что вы хотите показать пользователям.
Если у вас уже имеется отформатированная строка для тела, вы можете присвоить её свойству yiiwebResponse::$content
объекта запроса:
Yii::$app->response->content = 'hello world!';
Если ваши данные перед отправкой конечным пользователям нужно привести к определённому формату, вам следует установить значения
двух свойств: format и data. Свойство format
определяет, в каком формате следует возвращать данные из data. Например:
$response = Yii::$app->response;
$response->format = yiiwebResponse::FORMAT_JSON;
$response->data = ['message' => 'hello world'];
Yii из коробки имеет поддержку следующих форматов, каждый из которых реализован классом форматтера.
Вы можете настроить эти форматтеры или добавить новые через свойство yiiwebResponse::$formatters.
- HTML: реализуется классом yiiwebHtmlResponseFormatter.
- XML: реализуется классом yiiwebXmlResponseFormatter.
- JSON: реализуется классом yiiwebJsonResponseFormatter.
- JSONP: реализуется классом yiiwebJsonResponseFormatter.
Хотя тело запроса может быть явно установлено показанным выше способом, в большинстве случаев вы можете задавать его неявно
через возвращаемое значение методов действий. Типичный пример использования:
public function actionIndex()
{
return $this->render('index');
}
Действие index
в коде выше возвращает результат рендеринга представления index
. Возвращаемое значение будет взято
компонентом response
, отформатировано и затем отправлено пользователям.
Так как по умолчанию форматом ответа является HTML, в методе действия следует
вернуть строку. Если вы хотите использовать другой формат ответа, необходимо настроить его перед отправкой данных:
public function actionInfo()
{
Yii::$app->response->format = yiiwebResponse::FORMAT_JSON;
return [
'message' => 'hello world',
'code' => 100,
];
}
Как уже было сказано, кроме использования стандартного компонента приложения response
вы также можете создавать свои
объекты ответа и отправлять их конечным пользователям. Вы можете сделать это, возвращая такой объект в методе действия:
public function actionInfo()
{
return Yii::createObject([
'class' => 'yiiwebResponse',
'format' => yiiwebResponse::FORMAT_JSON,
'data' => [
'message' => 'hello world',
'code' => 100,
],
]);
}
Примечание: создавая собственные объекты ответов, вы не сможете воспользоваться конфигурацией компонента
response
,
настроенной вами в конфигурации приложения. Тем не менее, вы можете воспользоваться
внедрением зависимости, чтобы применить общую конфигурацию к вашим новым объектам ответа.
Перенаправление браузера ¶
Перенаправление браузера основано на отправке HTTP-заголовка Location
. Так как данная возможность широко применяется,
Yii имеет средства для её использования.
Вы можете перенаправить браузер пользователя на URL-адрес, вызвав метод yiiwebResponse::redirect(). Этот метод
использует указанный URL-адрес в качестве значения заголовка Location
и возвращает сам объект ответа. В методе действия
вы можете вызвать короткую версию этого метода — yiiwebController::redirect(). Например:
public function actionOld()
{
return $this->redirect('https://example.com/new', 301);
}
В приведённом выше коде метод действия возвращает результат redirect()
. Как говорилось выше, объект ответа,
возвращаемый методом действия, будет использоваться в качестве ответа конечным пользователям.
В коде, находящемся вне методов действий, следует использовать yiiwebResponse::redirect() и непосредственно после
него — метод yiiwebResponse::send(). Так можно быть уверенным, что к ответу не будет добавлено нежелательное
содержимое.
Yii::$app->response->redirect('https://example.com/new', 301)->send();
Информация: По умолчанию метод yiiwebResponse::redirect() устанавливает код состояния ответа равным 302, сообщая
браузеру, что запрашиваемый ресурс временно находится по другому URI-адресу. Вы можете передать код состояния
301, чтобы сообщить браузеру, что ресурс перемещён навсегда.
Если текущий запрос является AJAX-запросом, отправка заголовка Location
не заставит браузер автоматически
осуществить перенаправление. Чтобы решить эту задачу, метод yiiwebResponse::redirect() устанавливает значение
заголовка X-Redirect
равным URL для перенаправления. На стороне клиента вы можете написать JavaScript-код для чтения
значения этого заголовка и перенаправления браузера соответственно.
Информация: Yii поставляется с JavaScript-файлом
yii.js
, который предоставляет набор часто используемых
JavaScript-утилит, включая и перенаправление браузера на основе заголовкаX-Redirect
. Следовательно, если вы
используете этот JavaScript-файл (зарегистрировав пакет ресурсов yiiwebYiiAsset), вам не нужно писать
дополнительный код для поддержки AJAX-перенаправления.
Отправка файлов ¶
Как и перенаправление браузера, отправка файлов является ещё одной возможностью, основанной на определённых HTTP-заголовках.
Yii предоставляет набор методов для решения различных задач по отправке файлов. Все они поддерживают HTTP-заголовок range.
- yiiwebResponse::sendFile(): отправляет клиенту существующий файл.
- yiiwebResponse::sendContentAsFile(): отправляет клиенту строку как файл.
- yiiwebResponse::sendStreamAsFile(): отправляет клиенту существующий файловый поток как файл.
Эти методы имеют одинаковую сигнатуру и возвращают объект ответа. Если отправляемый файл очень велик, следует
использовать yiiwebResponse::sendStreamAsFile(), так как он более эффективно использует оперативную память.
Следующий пример показывает, как отправить файл в действии контроллера:
public function actionDownload()
{
return Yii::$app->response->sendFile('path/to/file.txt');
}
Чтобы быть уверенным, что к ответу не будет добавлено никакое
нежелательное содержимое, при вызове метода yiiwebResponse::sendFile() вне методов action, следует вызвать сразу после него yiiwebResponse::send().
Yii::$app->response->sendFile('path/to/file.txt')->send();
Некоторые Web-серверы поддерживают особый режим отправки файлов, который называется X-Sendfile. Идея в том, чтобы
перенаправить запрос файла Web-серверу, который отдаст файл пользователю самостоятельно. В результате Web-приложение
может завершиться раньше, пока Web-сервер ещё пересылает файл. Чтобы использовать эту возможность, воспользуйтесь
методом yiiwebResponse::xSendFile(). Далее приведены ссылки на то, как включить X-Sendfile
для популярных
Web-серверов:
- Apache: X-Sendfile
- Lighttpd v1.4: X-LIGHTTPD-send-file
- Lighttpd v1.5: X-Sendfile
- Nginx: X-Accel-Redirect
- Cherokee: X-Sendfile and X-Accel-Redirect
Отправка ответа ¶
Содержимое ответа не отправляется пользователю до вызова метода yiiwebResponse::send(). По умолчанию он вызывается
автоматически в конце метода yiibaseApplication::run(). Однако чтобы ответ был отправлен немедленно, вы можете
вызвать этот метод явно.
Для отправки ответа метод yiiwebResponse::send() выполняет следующие шаги:
- Инициируется событие yiiwebResponse::EVENT_BEFORE_SEND.
- Для форматирования данных ответа в содержимое ответа
вызывается метод yiiwebResponse::prepare() . - Инициируется событие yiiwebResponse::EVENT_AFTER_PREPARE.
- Для отправки зарегистрированных HTTP-заголовков вызывается метод yiiwebResponse::sendHeaders().
- Для отправки тела ответа вызывается метод yiiwebResponse::sendContent().
- Инициируется событие yiiwebResponse::EVENT_AFTER_SEND.
Повторный вызов yiiwebResponse::send() игнорируется. Это означает, что если ответ уже отправлен, то к нему уже
ничего не добавить.
Как видно, метод yiiwebResponse::send() инициирует несколько полезных событий. Реагируя на
эти события, можно настраивать или декорировать ответ.
Приветствую всех! Решил изучать vagrant и поднял на нем проект на yii2, все работало хорошо, но внезапно начала возникать ошибка 500 и никак не пойму причину. Сносил вагрант командой vagrant destroy и заново ставил vagrant up, но все равно ошибка 500. Прошу помочь понять причину возникновения этой ошибки и как исправить.
-
Вопрос заданболее трёх лет назад
-
1740 просмотров
http логи смотрим от сервера, затем от php.
смотрим также логи от приложения runtime/log/app.log.
также берем каждый запрос к бд и анализируем через explain наверняка индекса нету на большой таблице.
можно поставить newrealic или ему подобный мониторинг и найти все что тормозит еще быстрей.
Пригласить эксперта
Спасибо за ответы, посмотрел в логах, ошибка была в синтаксисе написанных мной файлов, исправил ошибки , сделал vagrant up и заработало
-
Показать ещё
Загружается…
13 июн. 2023, в 13:13
500 руб./за проект
13 июн. 2023, в 12:17
40000 руб./за проект
13 июн. 2023, в 11:15
5000 руб./за проект
Минуточку внимания
Обработка ошибок
Если при обработке запроса к RESTful API в запросе пользователя обнаруживается ошибка или происходит
что-то непредвиденное на сервере, вы можете просто выбрасывать исключение, чтобы уведомить пользователя о нештатной ситуации.
Если вы можете установить конкретную причину ошибки (например, запрошенный ресурс не существует), вам следует подумать
о том, чтобы выбрасывать исключение с соответствующим кодом состояния HTTP (например, [[yiiwebNotFoundHttpException]],
соответствующее коду состояния 404). Yii отправит ответ с соответствующим
HTTP-кодом и текстом. Он также включит в тело ответа сериализованное представление
исключения. Например:
HTTP/1.1 404 Not Found
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"name": "Not Found Exception",
"message": "The requested resource was not found.",
"code": 0,
"status": 404
}
Сводный список кодов состояния HTTP, используемых REST-фреймворком Yii:
200
: OK. Все сработало именно так, как и ожидалось.201
: Ресурс был успешно создан в ответ наPOST
-запрос. ЗаголовокLocation
содержит URL, указывающий на только что созданный ресурс.204
: Запрос обработан успешно, и в ответе нет содержимого (для запросаDELETE
, например).304
: Ресурс не изменялся. Можно использовать закэшированную версию.400
: Неверный запрос. Может быть связано с разнообразными проблемами на стороне пользователя, такими как неверные JSON-данные
в теле запроса, неправильные параметры действия, и т.д.401
: Аутентификация завершилась неудачно.403
: Аутентифицированному пользователю не разрешен доступ к указанной точке входа API.404
: Запрошенный ресурс не существует.405
: Метод не поддерживается. Сверьтесь со списком поддерживаемых HTTP-методов в заголовкеAllow
.415
: Не поддерживаемый тип данных. Запрашивается неправильный тип данных или номер версии.422
: Проверка данных завершилась неудачно (в ответе наPOST
-запрос, например). Подробные сообщения об ошибках смотрите в теле ответа.429
: Слишком много запросов. Запрос отклонен из-за превышения ограничения частоты запросов.500
: Внутренняя ошибка сервера. Возможная причина — ошибки в самой программе.
Свой формат ответа с ошибкой
Вам может понадобиться изменить формат ответа с ошибкой. Например, вместо использования разных статусов ответа HTTP
для разных ошибок, вы можете всегда отдавать статус 200, а реальный код статуса отдавать как часть JSON ответа:
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"success": false,
"data": {
"name": "Not Found Exception",
"message": "The requested resource was not found.",
"code": 0,
"status": 404
}
}
Для этого можно использовать событие beforeSend
компонента response
прямо в конфигурации приложения:
return [ // ... 'components' => [ 'response' => [ 'class' => 'yiiwebResponse', 'on beforeSend' => function ($event) { $response = $event->sender; if ($response->data !== null && !empty(Yii::$app->request->get('suppress_response_code'))) { $response->data = [ 'success' => $response->isSuccessful, 'data' => $response->data, ]; $response->statusCode = 200; } }, ], ], ];
Приведённый выше код изменит формат ответа (как для удачного запроса, так и для ошибок) если передан GET
-параметр
suppress_response_code
.
I had exactly the same problem. My website with ajax works perfectly in the localhost. but when i uploaded it to the server, I realized the ajax request where not workin returning the 500 internal error. And when i click the url it says that undefined variable.
Solution: Check the url of the ajax request:
before:
echo CHtml::textField('idsearch', '', array(
'onKeyUp' => CHtml::ajax(
array(
'type' => 'POST',
'dataType' => 'html',
'data' => array(
'id' => 'js:idsearch.value'),
'update' => '#dvfeeform',
'url' => CController::createUrl('student/searchajax'),
))
));
after editing the url to:
'url' => Yii::app()->createUrl('student/searchajax'),
it worked perfectly fine.
hope it may help someone someday
Стояло приложение Yii2 бэсик на сервере на всякий случай сообщаю php в консоли 5.4.16
перенес приложение на другой сервер, структура папок начинаю от корня / та же самая. на новом сервере php в консоли 5.3.3
база данных тоже перенсена.
На новом сервере получаю ошибку 500. если убрать htaccess пойти по прямому пути к индексному файлу приложения то он запускается криво, автолоадер подключается но на последней строке index.php где запускается приложение выскакивает 500ка
думал криво переписал файлы. переписал еще раз с сервера на сервер через scp, все четко переписано минуя загрузку на локальную машину, а ошибка все равно вылетает.
Куда смотреть я уже все логи и апача и php и что там еще есть сервака посмотрел. там нет ни единого намека на причину ошибки.
htaccess такой
Код: Выделить всё
Options +FollowSymLinks
IndexIgnore */*
RewriteEngine on
# Если запрос не начинается с web, добавляем его
RewriteCond %{REQUEST_URI} !^/(yii2-app-basic)
RewriteRule (.*) yii2-app-basic/web/$1
# Если файл или каталог не существует, идём к yii2-app-basic/web/index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . yii2-app-basic/web/index.php
Направьте пожалуйста.
Спасибо!