LoginSignup
36
38

More than 5 years have passed since last update.

PHPにおける実践的HTTPリクエストメソッド

Last updated at Posted at 2016-09-30

OPTIONSとか使ってる人いるんですかね。

HTTPリクエストメソッドとは

簡単に言うと、そのリクエストが何を目的にしているかを表明する取り決めだ。
詳しくは別記事などを参照のこと。
仕様はRFC2068RFC7540などで定義され、最新のHTTP/2ではGET/POST/PUT/DELETE/HEAD/OPTIONS/TRACE/CONNECTと8種類のHTTPリクエストメソッドが用意されている。
GETならデータを寄こせ、POSTなら登録しろ、DELETEなら削除しろ、とまあそんなかんじになる。

本来の姿

ベストプラクティスでは以下のようなURLが理想とされている。
 GET /tickets - チケットのリストを取得する
 GET /tickets/12 - 指定したチケットの情報を取得する
 POST /tickets - 新しいチケットを作成する
 PUT /tickets/12 - チケット #12 を更新する
 PATCH /tickets/12 - チケット #12 を部分的に更新する
 DELETE /tickets/12 - チケット #12 を削除する

まあ概ね同意ではあるのだが、
しかし残念、実はブラウザはGET/POST以外のHTTPリクエストメソッドを送ることができなかったりする。

そもそもHTMLのフォームはPUTやDELETEなどに対応してないうえ、TRACEは速攻で無効化され、かと思えばPATCHとかいう謎メソッドが増えてたりと、実のところGET/POST以外のHTTPリクエストメソッドはまともに使える状況ではない。

フレームワークの中にはPUT / DELETE / PATCHなどに対応しているものも存在しているが、実はこれPOSTしつつhiddenでmethod=putとかのパラメータを送ってるだけという代物で、要するにPOSTだ。

私的お薦め送信側

普通に画面の要件に従っておけばいいよ。
要するにリンクならGETだしフォームならPOSTだ。

GET

URLに全パラメータを含めるリクエストだ。
index.php?a=1&b=2みたいなやつ。

実はaタグでのリンクは通常GETしか送ることができない1
つまり、リンクをクリックしたら何かが更新されるような作りはREST違反だ。
しかし、だからといって、何かを更新するリンクがあったとして、リンクを踏んだのをJavaScriptで感知してPOSTに変換して送るなんて処理は本末転倒も甚だしい。
パラメータに?method=putとか書いて普通にGET送っとけばええやろ。

POST

パラメータをリクエストボディに含めるリクエスト。
リクエストのサイズ制限がGETよりずっと大きく、またデータがURLに含まれないので覗き見もされにくい2
formタグにmethod="POST"と書いておけばPOSTになる。
フォームをGETにする意味は全くないので、常にPOSTにしておいてかまわない。
詳細を表示するだけのボタンだってPOSTでいいぞ。
むしろふぉrm<form method="post" enctype="multipart/form-data" action="">って辞書登録しておくまである。

なお、POSTの場合でもactionに?id=1とか書けるし普通に$_GETで受け取れる。

私的お薦め受信側

$_REQUEST一択。

$_REQUEST

$_GET$_POST$_COOKIEをひとまとめで受け取ることができるスーパーグローバル変数3
送信側がリンクだろうがフォームだろうがAJAXだろうがその他のリクエストだろうがおかまいなしに、受信側は全く同じに書くことができる。
なお、PHPには$_PUT$_DELETEなどは存在しないし、普通に受け取ることもできない

各変数で同じキーが重複した場合、request_orderに従って何れかのパラメータが優先される。
index.php?id=1というURLにid=2をPOSTした場合、request_orderに従って$_REQUEST['id']=1になったり$_REQUEST['id']=2になったりする。
想定していない方が優先されて困るという場合があるかもしれないが、そもそも$_GET['id']$_POST['id']が違うなんて設計する方が悪いので、パラメータを見直すべきである。

なおCookieはPHPSESSID以外使わないから重なることはない。

理想と現実

現実はこんなもんだ。

 GET|POST /tickets.php?method=get - チケットのリストを取得する
 GET|POST /tickets.php?method=get&id=12 - 指定したチケットの情報を取得する
 GET|POST /tickets.php?method=post - 新しいチケットを作成する
 GET|POST /tickets.php?method=put&id=12 - チケット #12 を更新する
 GET|POST /tickets.php?method=delete&id=12 - チケット #12 を削除する

HTTPリクエストメソッドは完全に無視し、単にmethodパラメータだけで判断する。
省略したらgetにすると取り決めてもいいし、mod_rewriteで/tickets/put/12みたいにするのもいいだろう。
送信側でいちいちHTTPリクエストメソッドを分けたりPUTやDELETEを作り込んだりする必要もないし、はっきりいってこっちのほうが楽。

え?PATCH?PUTでええやん。

まとめ

全部$_REQUESTにする。

ただし、FWを導入しているなら、FWの流儀をあえて外す必要はない。
あくまでルーティングを自作する場合の思想である。
そしてFWを使わずにルーティングを自作する機会など、今時はほとんど無い。

従って、このエントリが役立つことは、あんまり無い。


  1. JavaScriptを使えばPOSTでもなんでもできるがまあ。 

  2. あくまでGETに比べればマシ程度の話であり、本気で隠蔽するならSSLを使わないといけない。 

  3. 最近は$_COOKIEはデフォルトでは外されている。 

36
38
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
36
38