クモのようにコツコツと

フロントエンドエンジニア イイダリョウの技術ブログ。略称「クモコツ」

フォームPHPはじめの一歩($_GETと$_POSTの違い)

HTMLのformタグはフロントエンドとサーバサイドの間を繋ぐ「架け橋」です。私はこれまでformタグまでは書いていましたが、データ送信には外部のPHPフォームプログラムを利用していました。今回は、フォームPHPの$_GET$_POSTを自分で書いて、動きの違いについて検証しました。

【目次】

フォームからサーバにデータを送信

通常のWebサイトはサーバ側からブラウザ(クライアント)側にページデータが送られますが、フォームがあればブラウザ側から入力データをサーバ側に送ることができます。

f:id:idr_zz:20190127145658p:plain

  • 通常のブラウジングではサーバからブラウザにページデータを送る一方通行
  • フォームがあるとブザウザからサーバに入力データを送ることができる

このフォームの入力データをサーバに送る仕組み(プログラム)を担っているのがPHPになります。

HTMLフォームの基本

まず最初に、簡単なHTMLフォームを作ります。

※参考:HTMLの基本はこちら
【HTMLの基本】書ける前に読む!HTML、CSS、JSの書式-2 - クモのようにコツコツと

作ったフォームはこちら。題して「クリエイター川柳」!

※参考:クリエイター川柳(HTML版)

上下に2つのフォームがありますね。見た目には違いがほとんどありません。

上のフォーム($_GET) f:id:idr_zz:20190127184626j:plain

<!--$_GET-->
<h2>今日の一句($_GET)</h2>
<form method="get" action="">
    <input type="text" name="ikku">
    <input type="submit" name="yomu" value="詠む">
</form>
  • formタグでinputタグ(2つ)を囲んでいる
  • formタグのmethod属性の値はgetaction属性の値は空
  • 一つ目のinputタグのtype属性はtextname属性はikku
  • 二つ目のinputタグのtype属性はsubmitname属性はyomuvalue属性は詠む

下のフォーム($_POST) f:id:idr_zz:20190127184639j:plain

<!--$_ POST-->
<h2>今日の一句($_POST)</h2>
<form method="post" action="">
    <input type="text" name="ikku">
    <input type="submit" name="yomu" value="詠む">
</form>
  • formタグのmethod属性の値はpost(その他のコードは同じ)

フォームHTMLの基本はformタグでinputタグを囲むことです。

※参考:<FORM>-HTMLタグリファレンス

type属性はinputタグの種類を意味します。textは一行テキスト、submitは送信ボタンです*1

name属性は項目の識別に使います。値が重複すると前の値が後ろの値に上書きされてしまいます。

value属性は送信ボタンに表示される文字列です*2

さて、この状態でフォームに何か文字を入力してみてください*3

どうですか?ページ上は何も変化がありませんね*4。フォームの入力データをサーバに送信するには、PHPなどのサーバサイド言語の協力が必要です*5

htmlファイルのphpファイル化

formタグのaction属性にhoge.phpなどを指定すると、送信ボタンを押したときにhoge.phpページに遷移して、そこのPHPコードを実行します。(空欄のままだとページは遷移しません)

私はこれまでaction属性にPHP工房 *6などのphpファイルを指定していました。

※参考:【MailForm01】PHPメールフォーム多機能版(著作権リンク無し)フリー(無料)|PHP工房

今回は既存のフォームプログラムを利用せず、自分でデータ送信のPHPコードを書いてみます。

※参考:PHPの基本はこちら
PHPの基本を理解するためにJSと比較する - クモのようにコツコツと

まずはindex.htmlファイルを複製してindex.phpという名前にします。これでaction属性が空欄のままでも、同じページ内のPHPコードが実行されます。

PHPコードを追記

フォームの下にPHPのコードを書きました。

※参考:http://ppp-php-test.herokuapp.com/php_form_test/index.php

上のフォーム($_GET) f:id:idr_zz:20190127223743j:plain

<!--$_GET-->
<h3>あなたの一句:</h3>
<p class="echo"><?php 
$ikku = $_GET["ikku"];
echo $ikku;    
?></p>
  • 変数$ikkuに変数$_GET内の配列ikkuプロパティの値を代入
  • echoで変数$ikkuを出力

下のフォーム($_POST) f:id:idr_zz:20190127223809j:plain

<!--$_ POST-->
<h3>あなたの一句:</h3>
<p class="echo"><?php 
$ikku = $_POST["ikku"];
echo $ikku;    
?></p>
  • 変数$ikkuに変数$_POST内の配列ikkuプロパティの値を代入
  • echoで変数$ikkuを出力

変数$_GETget属性のフォーム、変数$_POSTpost属性のフォームが紐づきます。

$_GET$_POSTの後ろについている角カッコ[]は配列を意味します。配列のプロパティはinputタグのname属性と紐づきます。

ファイルのコード上にはありませんが、このような配列に格納されているとイメージしてください。

<?php 
//get属性のフォームの値を格納
$_GET = [ name属性の値 => 入力値];

//post属性のフォームの値を格納
$_POST = [ name属性の値 => 入力値];
?>

今回は$_GET$_POSTのいずれもikkuを指定しているため、name属性がikkuinputタグの入力値を読み込みます。

$GETと$POSTのフォームを送信してみる

それでは、実際に2つのフォームを送信してみましょう!

まず上の$_GETのフォームで川柳を詠んでみます。

Laravelや ああLaravelや Laravelや

Laravelへの思いがしんみりと伝わってくる一句ですね。

f:id:idr_zz:20190127161127j:plain

「詠む」ボタンをクリック!

f:id:idr_zz:20190127161144j:plain

おお、先ほど詠んだ句が「あなたの一句」の下に表示されました!

次、下の$_POSTのフォームで川柳を詠んでみませう。

Railsや ああRailsや Railsや

こちらもRailsへの思いがしんみりと伝わってくる一句ですね。

f:id:idr_zz:20190127161428j:plain

「詠む」ボタンをクリック!

f:id:idr_zz:20190127161448j:plain

詠んだ句が「あなたの一句」の下に表示されました!!

さて、一見まったく同じ動きをしたように見えるこの2つのフォーム。いったいどんな違いがあるのでしょうか?イメージとしてはこのようになります。

  • $_GET=ハガキ(丸見えで送られるデータ)
  • $_POST=封筒(コッソリ送るデータ)

どういうことか?順番に見ていきます。

method="get"のフォームはクエリパラメータに値を渡す

ここで注目していただきたい場所があります。ブラウザのURLが表示されるツールバーの部分です。

このようになっていると思います。

http://ppp-php-test.herokuapp.com/php_form_test/index.php?ikku=Laravelや+ああLaravelや+Laravelや&yomu=詠む

※参考:http://ppp-php-test.herokuapp.com/php_form_test/index.php?ikku=Laravelや+ああLaravelや+Laravelや&yomu=詠む

うーむ…ファイル名index.phpの後ろになにやら怪しい文字列がツラツラと続いておりますね。。こういうの、迷惑メールのリンクURLにもよく付いていて警戒心を抱く方も多いかと思います。

この文字列は「クエリパラメータ」といいます。このような書式です。

//パラメータが一つ
URL?パラメータ名=値

//パラメータが複数
URL?パラメータ名=値&パラメータ名=値&パラメータ名=値
  • URLのあとの?がクエリパラメータの始まりの合図
  • パラメータと値が1対になり、パラメータ名=で繋がっている。
  • パラメータが複数の場合は2つ目以降は頭に&を付ける

よくある例としては検索結果ページに使われますね。例えば私のブログで「php」と検索すると下記のようなURLになります。

https://www.i-ryo.com/search?q=php
  • https://www.i-ryo.com/searchまでがURL
  • qがパラメータ名
  • phpが値

※参考:https://www.i-ryo.com/search?q=php

$_GETはクエリパラメータを格納する

冒頭のURLをもう一度みると

http://ppp-php-test.herokuapp.com/php_form_test/index.php?ikku=Laravelや+ああLaravelや+Laravelや&yomu=詠む
  • http://ppp-php-test.herokuapp.com/php_form_test/index.phpまではURL
  • ikkuパラメータの値はLaravelや+ああLaravelや+Laravelや
  • yomuパラメータの値は詠む

※参考:http://ppp-php-test.herokuapp.com/php_form_test/index.php?ikku=Laravelや+ああLaravelや+Laravelや&yomu=詠む

このikkuパラメータの値は上の$_GETフォームで詠んだ一句じゃないですか!五・七・五の間に入れたスペースは+になっていますね。

そう、method属性がgetのフォームには入力値をクエリパラメータに送る機能があるのです!そして$_GETにはクエリパラメータを読み込んで配列に格納する機能があります。

f:id:idr_zz:20190128204331p:plain

$_GETはあとから打ち替えられる

なお、クエリパラメータはURL欄にむき出しのため、あとから打ち替えることができてしまいます。

ためしにやってみましょう。

`http://ppp-php-test.herokuapp.com/php_form_test/index.php?ikku=Laravelだ+ああLaravelだ+Laravelだ&yomu=詠む`

クエリパラメータの「Laravelや」の「や」部分をすべて「だ」に打ち替えて、「Laravelだ」にしてみました。

ページをリロードすると…

※参考:http://ppp-php-test.herokuapp.com/php_form_test/index.php?ikku=Laravelだ+ああLaravelだ+Laravelだ&yomu=詠む

おお、「Laravelや」が「Laravelだ」に打ち変わりました! f:id:idr_zz:20190127164304j:plain

Laravelだ ああLaravelだ Laravelだ

Laravelへの強い気持ち強い愛が感じられる一句ですね。

$_GETのデータはハガキのように丸見えのため、あとから書き換えることができるわけです。(検索フォームなどはたいてい$_GETで送信されています)

$_POSTはリロードするとリセットされる

一方、下の$_POSTの方の「あなたの一句」はページをリロードするとリセットされてしまいます。

f:id:idr_zz:20190127164557j:plain

$_POSTはフォームの入力値を内部的に送信することを目的しているため、クエリパラメータを経由せずに、直接$_POSTの配列に格納します。

f:id:idr_zz:20190127180154p:plain

そのため、$_POSTに格納された値は別途、メール送信やデータベース保存などの関数に渡す必要があります。

$_POSTのデータは封筒のようにコッソリと送信されるため、あとから書き換えができません。(個人情報など気密性の高い情報は$_POSTで送るべきです)

最後に

ということで、シンプルなコードですが$_GET$_POSTの動きの違いが理解できました!

  • $_GETはフォームからクエリパラメータに送られた値を読み込んで配列に格納する
  • $_POSTはフォームの値を内部的に直接受け取って配列に格納する

次はこんなことをしてみたい。

  • $_POSTが受け取ったデータをメールに送信
  • $_POSTが受け取ったデータをデータベース保存

それではまた!

*1:他にラジオボタンのradio、チェックボックスのcheckboxなどがあります

*2:なお、inputタグ以外には複数行テキストのtextareaタグ、セレクトボックスのselectタグなどがあります。

*3:川柳でなくても構いませんw

*4:実は上の$_GETのフォームだけ、地味に変わっている箇所があるのですが、後述します

*5:かつてはCGIのフォームプログラムがよく使われていました

*6:いつも大変お世話になっております