Сцена: Недавно при создании PHP-сервиса мы столкнулись с проблемой. Структура-это YII. Мы отправляем данные через ПОЧТАЛЬОНА и выбираем в качестве режима отправки СООБЩЕНИЕ. Тело имеет три основных варианта 1、форма-данные 2、x-www-форма-url-код 3、необработанный
Когда выбрана форма-данные, данные записи обычно принимаются путем отправки, но когда выбран параметр raw+JSON (приложение/json), данные записи пусты.
В чем причина этой проблемы? Нам нужно начать с принципа реализации YII.
1. Отправляйте данные в формате JSON через curl, такие как код:
Затем на получающем конце получите с помощью $_POST и обнаружите, что печать пуста
Причина в том, что по умолчанию PHP распознает только тип данных стандарта application/x-www.form-url, поэтому он не может его получить и может только проходить через него.
// The first method
$post = $GLOBALS['HTTP_RAW_POST_DATA'];
// The second method
$post = file_get_contents("php://input");Получать
2. Если мы хотим пройти в рамках Yii2
$username = Yii::$app->request->post('username');
$password = Yii::$app->request->post('password');
Таким образом, чтобы получить параметры post, переданные в первой части с использованием режима curl JSON, мы обнаружили, что это невозможно, нам нужно установить компонент запроса yii 2.
'request' => [
'class' => 'yii\web\Request',
'parsers' => [
'application/json' => 'yii\web\JsonParser',
],
],
А потом мы пройдем через это.
$username = Yii::$app->request->post('username');
$password = Yii::$app->request->post('password');
Если вы напечатаете $_POST, вы обнаружите, что здесь все еще нет значения. Почему?
Далее мы проверяем исходный код Yii2 с помощью кода.
1. Откройте веб-запрос yii, чтобы найти метод post ():
public function post($name = null, $defaultValue = null)
{
if ($name === null) {
return $this->getBodyParams();
}
return $this->getBodyParam($name, $defaultValue);
}
Значение обнаружения задается параметром $this – > getBodyParam ($имя, $Значение по умолчанию).
Затем найдите этот метод, код выглядит следующим образом:
/**
* Returns the request parameters given in the request body.
*
* Request parameters are determined using the parsers configured in [[parsers]] property.
* If no parsers are configured for the current [[contentType]] it uses the PHP function `mb_parse_str()`
* to parse the [[rawBody|request body]].
* @return array the request parameters given in the request body.
* @throws \yii\base\InvalidConfigException if a registered parser does not implement the [[RequestParserInterface]].
* @see getMethod()
* @see getBodyParam()
* @see setBodyParams()
*/
public function getBodyParams()
{
if ($this->_bodyParams === null) {
if (isset($_POST[$this->methodParam])) {
$this->_bodyParams = $_POST;
unset($this->_bodyParams[$this->methodParam]);
return $this->_bodyParams;
}
$rawContentType = $this->getContentType();
if (($pos = strpos($rawContentType, ';')) !== false) {
// e.g. application/json; charset=UTF-8
$contentType = substr($rawContentType, 0, $pos);
} else {
$contentType = $rawContentType;
}
if (isset($this->parsers[$contentType])) {
$parser = Yii::createObject($this->parsers[$contentType]);
if (!($parser instanceof RequestParserInterface)) {
throw new InvalidConfigException("The '$contentType' request parser is invalid. It must implement the yii\web\RequestParserInterface.");
}
$this->_bodyParams = $parser->parse($this->getRawBody(), $rawContentType);
} elseif (isset($this->parsers['*'])) {
$parser = Yii::createObject($this->parsers['*']);
if (!($parser instanceof RequestParserInterface)) {
throw new InvalidConfigException("The fallback request parser is invalid. It must implement the yii\web\RequestParserInterface.");
}
$this->_bodyParams = $parser->parse($this->getRawBody(), $rawContentType);
} elseif ($this->getMethod() === 'POST') {
// PHP has already parsed the body so we have all params in $_POST
$this->_bodyParams = $_POST;
} else {
$this->_bodyParams = [];
mb_parse_str($this->getRawBody(), $this->_bodyParams);
}
}
return $this->_bodyParams;
}
Выведите $rawContentType = $this – > getContentType (); эту переменную, найдите ее значение: application/json, а затем посмотрите на функцию getContentType ()
public function getContentType()
{
if (isset($_SERVER['CONTENT_TYPE'])) {
return $_SERVER['CONTENT_TYPE'];
}
if (isset($_SERVER['HTTP_CONTENT_TYPE'])) {
//fix bug https://bugs.php.net/bug.php?id=66606
return $_SERVER['HTTP_CONTENT_TYPE'];
}
return null;
}
То есть, когда мы отправляем запросы curl в формате JSON, $_SERVER[‘CONTENT_TYPE’] имеет значение application/json.
2. Вернувшись к функции getBodyParams () выше, он продолжит выполнение следующего кода:
if (isset($this->parsers[$contentType])) {
$parser = Yii::createObject($this->parsers[$contentType]);
if (!($parser instanceof RequestParserInterface)) {
throw new InvalidConfigException("The '$contentType' request parser is invalid. It must implement the yii\web\RequestParserInterface.");
}
$this->_bodyParams = $parser->parse($this->getRawBody(), $rawContentType);
}
Анализатор $генерируется из анализатора YIIWEBJSON в анализаторах в приведенной ниже конфигурации компонента запроса, а затем через контейнер.
'request' => [
'class' => 'yii\web\Request',
'enableCookieValidation' => false,
'parsers' => [
'application/json' => 'yii\web\JsonParser',
],
],
Таким образом, возвращаемое значение – $parser – > parse ($this – > getRawBody (), $rawContentType); возвращаемое значение – $parser – > parse ($this – > getRawBody (), $rawContentType).
3. Сначала давайте рассмотрим первый переданный параметр, который является функцией $this – > getRawBody (). Код выглядит следующим образом:
public function getRawBody()
{
if ($this->_rawBody === null) {
$this->_rawBody = file_get_contents('php://input');
}
return $this->_rawBody;
}
С помощью этой функции, возвращаясь к тому, что мы говорили ранее, мы можем пройти
// The first method
$post = $GLOBALS['HTTP_RAW_POST_DATA'];
// The second method
$post = file_get_contents("php://input");Эти два метода получают данные JSON, передаваемые curl json, yii2 использует второй метод.
Затем мы открываем веб-анализатор yii Json
/**
* Parses a HTTP request body.
* @param string $rawBody the raw HTTP request body.
* @param string $contentType the content type specified for the request body.
* @return array parameters parsed from the request body
* @throws BadRequestHttpException if the body contains invalid json and [[throwException]] is `true`.
*/
public function parse($rawBody, $contentType)
{
try {
$parameters = Json::decode($rawBody, $this->asArray);
return $parameters === null ? [] : $parameters;
} catch (InvalidParamException $e) {
if ($this->throwException) {
throw new BadRequestHttpException('Invalid JSON data in request body: ' . $e->getMessage());
}
return [];
}
}
Здесь вы можете видеть, что переданный JSON преобразуется в массив, а затем Yii:: request – > post (‘имя пользователя’) принимает значение из возвращенного массива.
Резюме:
1. В рамках Yii2 вместо методов $_POST $_GET следует использовать инкапсулированные методы post () и get (), поскольку эти два метода не равны.
2. Когда Yii2 создает api, если он в формате JSON для передачи данных, не забудьте добавить конфигурацию в компонент запроса:
'request' => [
'class' => 'yii\web\Request',
'parsers' => [
'application/json' => 'yii\web\JsonParser',
],
],