Мене спрямовують використовувати метод php://input
замість того, $_POST
щоб взаємодіяти з запитами Ajax від JQuery. Що я не розумію, це переваги використання цього проти глобального методу $_POST
або $_GET
.
Мене спрямовують використовувати метод php://input
замість того, $_POST
щоб взаємодіяти з запитами Ajax від JQuery. Що я не розумію, це переваги використання цього проти глобального методу $_POST
або $_GET
.
Відповіді:
Причина полягає в тому, що php://input
повертає всі необроблені дані після HTTP-заголовків запиту, незалежно від типу вмісту.
Суперглобальний PHP $_POST
, тільки повинен містити дані, які є будь-якими
application/x-www-form-urlencoded
(стандартний тип вмісту для простих форм-повідомлень) абоmultipart/form-data
(в основному використовується для завантаження файлів)Це тому, що це єдині типи вмісту, які повинні підтримувати користувальницькі агенти . Тож сервер і PHP традиційно не очікують отримання іншого типу контенту (це не означає, що вони не могли).
Отже, якщо ви просто розмістіть старий хороший HTML-код form
, запит виглядає приблизно так:
POST /page.php HTTP/1.1
key1=value1&key2=value2&key3=value3
Але якщо ви багато працюєте з Ajax, ця ймовірність включає також обмін більш складними даними з типами (string, int, bool) та структурами (масиви, об'єкти), тому в більшості випадків JSON - найкращий вибір. Але запит з корисним навантаженням JSON виглядатиме приблизно так:
POST /page.php HTTP/1.1
{"key1":"value1","key2":"value2","key3":"value3"}
Вміст тепер буде application/json
(або принаймні жодним із вищезгаданих), тому PHP- $_POST
wrapper не знає, як з цим впоратися.
Дані все ще є, ви просто не можете отримати доступ до них через обгортку. Тож вам потрібно його самостійно отримати в сирому форматі file_get_contents('php://input')
(до тих пір, поки це не multipart/form-data
-кодовано ).
Це також спосіб доступу до XML-даних або будь-якого іншого нестандартного типу вмісту.
application/json
як дійсне джерело даних для $_POST
масиву. І навіть є опубліковані запити на саме таку підтримку.
php://input
може дати вам необроблені байти даних. Це корисно, якщо дані POSTed - це кодована JSON структура, що часто буває для запиту AJAX POST.
Ось функція робити саме це:
/**
* Returns the JSON encoded POST data, if any, as an object.
*
* @return Object|null
*/
private function retrieveJsonPostData()
{
// get the raw POST data
$rawData = file_get_contents("php://input");
// this returns null if not valid json
return json_decode($rawData);
}
$_POST
Масив є більш корисним , коли ви обробки даних ключ-значення з форми, представленої традиційним POST. Це працює лише в тому випадку, якщо дані POSTed зазвичай є розпізнаним форматом application/x-www-form-urlencoded
(детальніше див. Http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4 ).
true
як другий параметр до json_decode
, він поверне асоціативний масив.
Якщо дані публікації неправильно сформовані, $ _POST нічого не міститиме. Тим не менш, вхід php: // матиме неправильно сформовану рядок.
Наприклад, є деякі програми ajax, які не формують правильну послідовність розміщення ключа-значення для завантаження файлу, а просто скидають весь файл у вигляді даних публікації, без імен змінних чи нічого. $ _POST буде порожнім, $ _FILES також порожнім, а вхід php: // буде містити точний файл, записаний у вигляді рядка.
PHP не розрахований на те, щоб явно надати вам такий REST (GET, POST, PUT, PATCH, DELETE), як інтерфейс для обробки HTTP-запитів .
Однак $_POST
, $_GET
і $_FILES
суперглобального , а функція filter_input_array()
дуже корисні для потреб середньої людини / непрофесіонала.
Прихованою перевагою номер 1 $_POST
(і $_GET
) є те, що PHP автоматично вводить ваші вхідні дані автоматично . Ви навіть не замислюєтеся про те, щоб це зробити, особливо для параметрів рядка запиту в стандартному GET-запиті.
Зважаючи на це, коли ви просуваєтесь у своїх знаннях з програмування та хочете використовувати XmlHttpRequest
об’єкт JavaScript (jQuery для деяких), ви побачите обмеження цієї схеми.
$_POST
обмежує використання двох типів носія у Content-Type
заголовку HTTP :
application/x-www-form-urlencoded
, іmultipart/form-data
Таким чином, якщо ви хочете відправити значення даних на PHP на сервері, і вони відображаються в $_POST
суперглобалі , вам потрібно urlencode їх на стороні клієнта і надіслати ці дані як пари ключів / значень - це незручний крок для новачків (особливо, намагаючись з’ясувати, чи потребують різних частин URL-адреси різні форми кодування urlencoding: звичайні, необроблені тощо).
Для всіх користувачів jQuery $.ajax()
метод перетворює ваш JSON в закодовані URL-адреси пари / значення, перш ніж передавати їх серверу. Ви можете змінити цю поведінку, встановивши processData: false
. Просто прочитайте документацію $ .ajax () і не забудьте надіслати правильний тип носія у заголовку Content-Type.
Як правило, якщо ви робите звичайні, синхронні (коли вся сторінка перемальовує) запити HTTP із формою HTML, користувальницький агент (веб-браузер) перекодує ваші дані форми для вас. Якщо ви хочете робити асинхронні запити HTTP за допомогою XmlHttpRequest
об'єкта, вам слід створити рядок, що кодується urlencoded, і надіслати його, якщо ви хочете, щоб ці дані відображалися в $_POST
надглобальному .
Перетворення з масиву JavaScript або об'єкта в рядок, що кодується URL, турбує багатьох розробників (навіть з новими API, такими як Form Data ). Вони, скоріше, зможуть просто надіслати JSON, і це було б більш ефективно для клієнтського коду.
Пам'ятайте (підморгнути, підморгнути), середній веб-розробник не вчиться XmlHttpRequest
безпосередньо використовувати об’єкт, глобальні функції, функції рядка, функції масиву та регулярні вирази, як ви і я ;-). Урленкодування для них - кошмар. ;-)
Відсутність PHP у інтуїтивно зрозумілому керуванні XML та JSON багатьох людей відключає. Ви б могли подумати, що зараз це буде частиною PHP (зітхаючи).
XML, JSON і YAML мають всі типи носіїв, які можна помістити в Content-Type
заголовк HTTP .
Подивіться, скільки типів медіа (раніше типів MIME) визначено IANA.
Подивіться, скільки є заголовків HTTP .
Використання php://input
потоку дозволяє обійти рівень сидіння / тримання за дитину абстракції, який PHP змусив у світі. :-) З великою силою приходить велика відповідальність!
Тепер, перш ніж розібратися зі значеннями даних, що передаються через php://input
, ви повинні / повинні зробити кілька речей.
AH, HA! Так, можливо, ви хочете, щоб потік даних, що надсилається у вашу заявку, був закодований UTF-8, але як ви можете дізнатися, є він чи ні?
php://input
.Чи збираєтесь ви намагатися обробляти дані потоку, не знаючи, скільки спочатку? Це жахлива ідея . Ви не можете покладатися виключно на HTTP- Content-Length
заголовок для вказівки щодо розміру потокового входу, оскільки він може бути підробленим.
Вам знадобиться:
Чи збираєтесь ви намагатися перетворити дані потоку в UTF-8, не знаючи поточного кодування потоку? Як? Фільтр потокового потоку iconv ( приклад фільтра потокового потоку iconv ), схоже, бажає кодування, що починається і закінчується, як це.
'convert.iconv.ISO-8859-1/UTF-8'
Таким чином, якщо ви сумлінні, вам знадобляться:
( Оновлення : 'convert.iconv.UTF-8/UTF-8'
примусить усе до UTF-8, але вам все одно доведеться враховувати символи, які бібліотека iconv може не знати, як перекладати. Іншими словами, ви повинні дещо визначити, яку дію зробити, коли символ неможливо перекласти : 1) Вставте персонаж манекена, 2) Провал / кидок та виняток).
Ви не можете покладатися виключно на HTTP- Content-Encoding
заголовок, оскільки це може означати щось на зразок стиснення, як у наступному. Це не те, про що ви хочете прийняти рішення щодо ікони.
Content-Encoding: gzip
Частина I: Пов’язаний із запитом HTTP
Частина II: Поточні дані
Частина III: Пов'язані з типом даних
(Пам'ятайте, що дані все ще можуть бути кодованою URL-адресою, яку необхідно потім розібрати та розшифрувати URL).
Частина IV: Пов'язані зі значенням даних
Фільтруйте вхідні дані.
Перевірка вхідних даних.
$_POST
Суперглобальний, поряд з php.ini настройки для обмеження на вхід, простіше для обивателя. Однак робота з кодуванням символів набагато інтуїтивніша та ефективніша при використанні потоків, оскільки немає необхідності прокручувати суперглобали (або масиви, як правило), щоб перевірити вхідні значення на правильне кодування.
Тому я написав функцію, яка б отримувала дані POST з потоку вводу php: // .
Таким чином, завдання тут було переключитись на метод запиту PUT, DELETE OR PATCH і все одно отримати дані про публікацію, надіслані з цим запитом.
Я поділяю це можливо для когось із подібним викликом. Функція нижче - це те, що я придумав, і воно працює. Я сподіваюся, що це допомагає!
/**
* @method Post getPostData
* @return array
*
* Convert Content-Disposition to a post data
*/
function getPostData() : array
{
// @var string $input
$input = file_get_contents('php://input');
// continue if $_POST is empty
if (strlen($input) > 0 && count($_POST) == 0 || count($_POST) > 0) :
$postsize = "---".sha1(strlen($input))."---";
preg_match_all('/([-]{2,})([^\s]+)[\n|\s]{0,}/', $input, $match);
// update input
if (count($match) > 0) $input = preg_replace('/([-]{2,})([^\s]+)[\n|\s]{0,}/', '', $input);
// extract the content-disposition
preg_match_all("/(Content-Disposition: form-data; name=)+(.*)/m", $input, $matches);
// let's get the keys
if (count($matches) > 0 && count($matches[0]) > 0)
{
$keys = $matches[2];
foreach ($keys as $index => $key) :
$key = trim($key);
$key = preg_replace('/^["]/','',$key);
$key = preg_replace('/["]$/','',$key);
$key = preg_replace('/[\s]/','',$key);
$keys[$index] = $key;
endforeach;
$input = preg_replace("/(Content-Disposition: form-data; name=)+(.*)/m", $postsize, $input);
$input = preg_replace("/(Content-Length: )+([^\n]+)/im", '', $input);
// now let's get key value
$inputArr = explode($postsize, $input);
// @var array $values
$values = [];
foreach ($inputArr as $index => $val) :
$val = preg_replace('/[\n]/','',$val);
if (preg_match('/[\S]/', $val)) $values[$index] = trim($val);
endforeach;
// now combine the key to the values
$post = [];
// @var array $value
$value = [];
// update value
foreach ($values as $i => $val) $value[] = $val;
// push to post
foreach ($keys as $x => $key) $post[$key] = isset($value[$x]) ? $value[$x] : '';
if (is_array($post)) :
$newPost = [];
foreach ($post as $key => $val) :
if (preg_match('/[\[]/', $key)) :
$k = substr($key, 0, strpos($key, '['));
$child = substr($key, strpos($key, '['));
$child = preg_replace('/[\[|\]]/','', $child);
$newPost[$k][$child] = $val;
else:
$newPost[$key] = $val;
endif;
endforeach;
$_POST = count($newPost) > 0 ? $newPost : $post;
endif;
}
endif;
// return post array
return $_POST;
}
Простий приклад того, як ним користуватися
<?php
if(!isset($_POST) || empty($_POST)) {
?>
<form name="form1" method="post" action="">
<input type="text" name="textfield"><br />
<input type="submit" name="Submit" value="submit">
</form>
<?php
} else {
$example = file_get_contents("php://input");
echo $example; }
?>