PHP 用於開發 webservice 的 API 接口與客戶端作數據交互時不必定會使用 PHP 能夠處理的數據格式進行通訊,好比 API 經常使用的 json xml,在此場景下咱們須要使用其餘的方式獲取客戶端發來的數據而後進行處理,下面咱們就實例模擬下客戶端請求 PHP API 場景下的數據交互方式。
php
同時要理解 get 請求並未攜帶表單數據,get 請求的本質是請求服務器的某一資源,其向服務器發送的數據都位於請求頭的 Query String/Query Path 中,請求頭是 uri,注意理解 get 請求的語意,是去服務器獲取資源而不是向服務器發送「數據」。 post 請求則是載有 Form Data 即表單數據的, 是想服務器發送 「數據」 的
web
get postjson
能夠看出get的參數都是附在請求頭中,並不像post中有content-length /content-type /from data 這些描述請求攜帶的數據內容的屬性值
服務器
PHP 支持的數據格式(注意:這裏說的支持不是指簡單的獲取到,意爲能夠進行自動處理,自動填充到 $_POST/ $_FILES中去,再次強調,get 請求並無向服務器發送「數據」,它是取,不是存,因此 $_GET 的是參數而不是數據)
app
application/x-www-form-urlencoded 普通的表單數據post
multipart/form-data 上傳文件的表單 enctype="multipart/form-data"測試
PHP 不支持的數據格式url
application/jsonspa
application/xml
code
不能處理但能夠獲取到,你能夠本身手動處理,參照表
application/x-www-form-urlencoded | multipart/form-data | application/json | application/xml | |
php://input | 可獲取 | 不可獲取 | 可獲取 | 可獲取 |
$_POST | 可獲取 | 可獲取 | 不可獲取 | 不可獲取 |
$HTTP_RAW_POST_DATA | 可獲取 | 不可獲取 | 可獲取 | 可獲取 |
PS: $HTTP_RAW_POST_DATA 已經被 PHP7 廢棄,緣由是 php://input 徹底囊括了它的全部功能,且其對服務器的壓力要比 php://input 大不少,最懦弱的是它默認配置下是讓位 $_POST 的,若是 $_POST 能處理數據的話他就得靠邊站,固然你能夠配置 php.ini 將 always_populate_raw_post_data 配置項打開,則會一直填充其所能識別的數據,即使 $_POST 的也能處理。
php://input: 除數據類型爲 multipart/form-data 的不能識別外,其餘格式均可以獲取,然後咱們能夠根據數據類型處理
$_POST: 能夠識別 application/x-www-form-urlencoded multipart/form-data 格式,json xml 沒法識別
$HTTP_RAW_POST_DATA :識別能力與 php://input 相同,默認配置下與 $_POST 互斥且優先級低於 $_POST
先貼出服務端代碼
注意當發送的數據爲 multipart/form-data 時 PHP 會將文件類型的數據存放在 $_FILES 中,文本的存放於 $_POST 中,但他們是同一組的,都是 from data 中的數據,與 $_GET 是不一樣的,$_GET 中填充的是請求頭中 Query String 的參數
<?php /** * @author sallency * @date 2016-3-4 11:03:23 * @desc 簡單模擬PHP做爲API時如何處理各類格式的數據 */ error_reporting(0); echo "==== 客戶端發送的數據格式 =====" . PHP_EOL; echo "REQUEST_METHOD: " . $_SERVER['REQUEST_METHOD'] . PHP_EOL; echo "ACCEPT: " . $_SERVER['HTTP_ACCEPT'] . PHP_EOL; echo "CONTENT_TYPE: " . ($_SERVER['CONTENT_TYPE'] ? $_SERVER['CONTENT_TYPE'] : "null") . PHP_EOL; echo PHP_EOL . "===== php://input 數據 ========" . PHP_EOL; echo file_get_contents('php://input') . PHP_EOL; echo PHP_EOL . '===== $_POST 數據 =============' . PHP_EOL; print_r($_POST); //當 multipart/form-data 類型時文件數據是存放在 $_FILES 中的 文本則 $_POST 中 echo PHP_EOL . '===== $_FILES 數據 =============' . PHP_EOL; print_r($_FILES); echo PHP_EOL . '===== $HTTP_RAW_POST_DATA =====' . PHP_EOL; echo $HTTP_RAW_POST_DATA ? $HTTP_RAW_POST_DATA : 'null' . PHP_EOL; ?>
一、發送 application/x-www-form-urlencoded 標準數據
能夠看出 php://input 和 $_POST/$_FILES 裏都能正常識別接收此類型的數據,其實 $_HTTP_RAW_POST_DATA 也能接受,但咱們說過默認狀況下它和 $_POST/$_FILES 是互斥且優先級低,因此 $_POST/$_FILES 中有數據時它就不會被填充了,可修改配置讓他一直填充本身可識別的數據。
二、發送 multipart/form-data
php://input 和 $HTTP_RAW_POST_DATA 爲空,說明它倆沒法識別此類行的數據流(其實也只是不能識別此類行的,其餘的都沒問題),$_POST/$_FILES 則能夠正常識別
三、發送 application/json 格式
數據體:
php://input 和 $HTTP_RAW_POST_DATA 可識別, $_POST 則沒法識別
四、發送 application/xml 格式
數據體:
php://input 和 $HTTP_RAW_POST_DATA 可識別, $_POST 則沒法識別
固然還有不少其餘的數據類型咱們就不作測試了,你們能夠本身動手。
application/x-www-form-urlencoded 是 PHP 的標準數據流類型, 能夠被三者識別
multipart/form-data 只能被 $_POST/$_FILES 識別處理,另外的二者沒法識別
application/json application/xml 等就只能被 php://input 和 $HTTP_RAW_POST_DATA 識別了,這也是咱們平常開發接口時每每使用 php://input 數據輸入流來獲取客戶端請求攜帶的數據
PS: 除了 POST 動做可攜帶數據體, PUT/PATCH/OPTIONS/HEAD/DELETE動做也均可以攜帶數據體,它們不像 POST 動做數據會被自動填充處理, 沒有對應的全局變量,這時咱們就可使用 php://input 來獲取此類動做所攜帶的原始數據。
GET/VIEW 動做不攜帶數據流因此三者都會是空,但 $_GET 會被填充
PHP 的 $_POST 中只會填充數據格式OK的 POST 動做的數據, 但 POST/PUT/PATCH/DELETE/OPTION 在數據格式符合的前提下請求會填充到 php://input 中,$HTTP_RAW_POST_DATA 則沒法響應 PUT/PATCH/DELETE/OPTION 動做的數據,例如:
PUT 請求
PATCH 請求
DELETE請求
OPTIONS 請求
HEAD 請求則返回響應頭信息