[2020/12/12] PHP 標準関数その3・変数の整数型への変換を行う関数(intval)について (No.247)
[2020/12/11] PHP 標準関数その2・変数の存在チェック及び解除を行う関数(isset, unset)について (No.246)
[2020/12/11] PHP 標準関数その1・文字列の分割・結合を行う関数(explode, implode)について (No.245)
[2020/12/09] PHP 問合せフォーム等の入力文字列の半角・全角変換について (No.244)
[2020/12/08] PHP QR-CODE をブラウザに表示する簡単な方法 (No.243)
-
×
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
-
変数の整数型への変換を行う関数である intval について説明します。
■intval関数
先ずは intval 関数ですが以下の様な定義になっています。(PHP の正式な説明サイトより)
intval ( mixed $var [, int $base = 10 ] ) : int [説明] 変数の整数としての値を取得する。 指定された値 base を基数(デフォルトは 10)とする、var の int としての値を返します。 オブジェクトに intval() を使用することはできません。その場合は E_NOTICE レベルのエラーを発して 1 を返します。 [パラメータ ] $var :整数に変換する値(変数)。 $base :変換のための基数。 [返り値] 成功時は var の整数値、失敗時は 0。 空の配列の場合は 0、空でない配列の場合は 1 を返します。
それでは、簡単な例のスクリプトを以下に示します。<?php /* f3-intval-1.php */ // 文字列で数値として成り立つデータを設定 $data = "100"; // 整数変換 $intData = intval($data); // 結果を表示 var_dump($intData); </html>
これをWindowsコマンドプロンプトで実行すると以下の表示になります。
C:\xampp\htdocs\_test>php f3-intval-1.php int(100)
■intval関数を使った各種の例
isset関数を使った、いろんな場合に付いて調べてみます。
<?php /* f3-intval-2.php */ var_dump(intval(100)); // 整数 var_dump(intval(100.5)); // 浮動小数点数 var_dump(intval("100")); // 文字列の整数形式 var_dump(intval("100.5")); // 文字列の浮動小数点数形式 var_dump(intval("")); // 空文字列 echo "\n"; var_dump(intval(true)); // boolean:true var_dump(intval(false)); // boolean:false var_dump(intval(null)); // null echo "\n"; var_dump(intval(array())); // 空の配列 var_dump(intval(array("a", "b"))); // 中身のある配列 echo "\n"; var_dump(intval("abcd")); // 数値を表現しない文字列(半角) var_dump(intval("あいう")); // 数値を表現しない文字列(全角) </html>
これをWindowsコマンドプロンプトで実行すると以下の表示になります。 (... 以降は説明で付けただけです。)
C:\xampp\htdocs\_test>php f3-intval-2.php int(100) ... 整数 int(100) ... 浮動小数点数 int(100) ... 文字列の整数形式 int(100) ... 文字列の浮動小数点数形式 int(0) ... 空文字列 int(1) ... boolean:true int(0) ... boolean:false int(0) ... null int(0) ... 空の配列 int(1) ... 中身のある配列 int(0) ... 数値を表現しない文字列(半角) int(0) ... 数値を表現しない文字列(全角)
null が「0」に変換され、配列の中身の有り無しで「1」「0」が変換されるのが分かります。
また、一番注意が必要なのは数値を表現できない文字列は「0」変換されることです。 この性質を暗黙の了解的に使って「0」だからと処理をするのはあまり良くないと思われます。
(処理の結果か、もしくはバグでそうなることがありますが、なるべく避けるべきは。)
■intval関数とデータ型の注意点
intval 関数で返される値は int型 であり、文字列型のデータと比較する場合は注意が必要です。
以下に 比較演算子 による違いをスクリプトで示します。<?php /* f3-intval-3.php */ // Windowsコマンドプロンプトで[XAMPP]のPHPで表示を Shift-JIS にする為の設定 ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // 数字で数値を宣言 $strData = "100"; // int型数値に変換 $intData = intval($strData); // 単なる比較 echo "単なる比較 : "; if ($strData == $intData) { echo "データは一致する。\n"; } else { echo "データは一致しない。\n"; } // データ型も含めた比較 echo "データ型も含めた比較 : "; if ($strData === $intData) { echo "データは一致する。\n"; } else { echo "データは一致しない。\n"; } ?>
これをWindowsコマンドプロンプトで実行すると以下の表示になります。
C:\xampp\htdocs\_test>php f3-intval-3.php 単なる比較 : データは一致する。 データ型も含めた比較 : データは一致しない。
ここで 比較演算子 の動きについて注意が必要で、 比較演算子 の 前 と 後 が共に数値形式の文字列の場合、 または、どちらか一方が数値形式の文字列の場合に、数値に変換して比較が行われます。 このため、上記の例で「$strData」は文字列の "100" ですが、数値の 100 として扱われ、比較が行われた結果、等しいものと判断されます。
但し、「===」「!==」の 比較演算子 はデータ型を含めての比較になるため、上記では等しくないと判断されます。
以下に 比較演算子 「==」の例を示します。<?php /* f3-intval-4.php */ var_dump( 100 == "100" ); var_dump( 100 == "00100" ); var_dump( 100 == " 100" ); var_dump( 100 == "100.5" ); var_dump( 0 == "aaa" ); ?>
これをWindowsコマンドプロンプトで実行すると以下の表示になります。
C:\xampp\htdocs\_test>php f3-intval-4.php bool(true) bool(true) bool(true) bool(false) bool(true)
文字列の部分が数値に変換されて判定されているのが分かります。最後の "aaa" は「0」に変換されるので等しくなります。
ところで、この数値への変換は 比較演算子 の他に switch でも行われるので更に注意が必要です。 以下のスクリプトを見て下さい。<?php /* f3-intval-5.php */ // Windowsコマンドプロンプトで[XAMPP]のPHPで表示を Shift-JIS にする為の設定 ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // 仮の swicth の判定値の宣言 $strSwicth = "a"; // 文字列のみの判断 switch ($strSwicth) { case "a": echo 'swicth で「"a"」の判断'."\n"; break; case "b": echo 'swicth で「"b"」の判断'."\n"; break; } // 最初に数値[0]の判断後、文字列の判断 switch ($strSwicth) { case 0: echo 'swicth で「0」の判断'."\n"; break; case "a": echo 'swicth で「"a"」の判断'."\n"; break; case "b": echo 'swicth で「"b"」の判断'."\n"; break; } ?>
これをWindowsコマンドプロンプトで実行すると以下の表示になります。
C:\xampp\htdocs\_test>php f3-intval-5.php swicth で「"a"」の判断 swicth で「0」の判断
最初の switch 文では 「case "a":」の所でヒットしますが、 2番目の switch 文では 「case 0:」のところで判定する値が数値なので「$strSwicth」を数値変換し "a" は数値ではないので「0」に変換され そのためそこでヒットする様になります。
PR -
変数の存在チェックを行う関数である isset 及び、変数の割り当てを解除する unset について説明します。
■isset関数
先ずは isset 関数ですが以下の様な定義になっています。(PHP の正式な説明サイトより)
isset ( mixed $var , mixed ...$vars ) : bool [説明] 変数が宣言されていること、そして null とは異なることを検査します。 [パラメータ ] $var :チェック対象変数。 $vars :その他のチェック対象変数。 [返り値] 変数が存在し null でなければ true、それ以外は false を返す。 変数が複数指定された場合は、全ての変数が存在し null でなければ true、それ以外は false を返す。
それでは、簡単な例のスクリプトを以下に示します。 (尚、3行目の設定はWindowsコマンドプロンプトでの実行時に、コンソールへの出力を Shift-JIS にする為のものです)<?php /* f1-isset-1.php */ // Windowsコマンドプロンプトで[XAMPP]のPHPで表示を Shift-JIS にする為の設定 ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // 変数が宣言されていない状況でチェック if (isset($data) == true) { echo "\$data は宣言されています。\n"; } else { echo "\$data は宣言されていないか null です。\n"; } // 変数を宣言した状況でチェック $data = "test"; if (isset($data) == true) { echo "\$data は宣言されています。\n"; } else { echo "\$data は宣言されていないか null です。\n"; } // 変数を null 設定した状況でチェック $data = null; if (isset($data) == true) { echo "\$data は宣言されています。\n"; } else { echo "\$data は宣言されていないか null です。\n"; } </html>
これをWindowsコマンドプロンプトで実行すると以下の表示になります。
C:\xampp\htdocs\_test>php f2-isset-1.php $data は宣言されていないか null です。 $data は宣言されています。 $data は宣言されていないか null です。
さらに、関数パラメータには配列も指定することで、配列にキー値で指定された要素の存在チェックが確認できます。 以下のその例を示します。
<?php /* f2-isset-2.php */ // Windowsコマンドプロンプトで[XAMPP]のPHPで表示を Shift-JIS にする為の設定 ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // 配列を宣言 $arr = array(0 => "11111", // KEY:数値 "key1" => "22222", // KEY:文字列 "key2" => array("test" => "abcdef")); // KEY:文字列で入れ子で配列 // 存在する数値KEYのチェック if (isset($arr[0]) == true) { echo '$arr[0] は宣言されています。'."\n"; } else { echo '$arr[0] は宣言されていないか null です。'."\n"; } // 存在しない数値KEYのチェック if (isset($arr[1]) == true) { echo '$arr[1] は宣言されています。'."\n"; } else { echo '$arr[1] は宣言されていないか null です。'."\n"; } // 存在する文字列KEYのチェック if (isset($arr["key1"]) == true) { echo '$arr["key1"] は宣言されています。'."\n"; } else { echo '$arr["key1"] は宣言されていないか null です。'."\n"; } // 存在しない文字列KEYのチェック if (isset($arr["key0"]) == true) { echo '$arr["key0"] は宣言されています。'."\n"; } else { echo '$arr["key0"] は宣言されていないか null です。'."\n"; } // 入れ子で配列の存在する文字列KEYのチェック if (isset($arr["key2"]["test"]) == true) { echo '$arr["key2"]["test"] は宣言されています。'."\n"; } else { echo '$arr["key2"]["test"] は宣言されていないか null です。'."\n"; } // 入れ子で配列の存在しない文字列KEYのチェック if (isset($arr["key2"]["test1"]) == true) { echo '$arr["key2"]["test1"] は宣言されています。'."\n"; } else { echo '$arr["key2"]["test1"] は宣言されていないか null です。'."\n"; } // 変数を null 設定した状況でチェック $arr["key2"]["test"] = null; if (isset($arr["key2"]["test"]) == true) { echo '$arr["key2"]["test"] は宣言されています。'."\n"; } else { echo '$arr["key2"]["test"] は宣言されていないか null です。'."\n"; } </html>
これをWindowsコマンドプロンプトで実行すると以下の表示になります。
C:\xampp\htdocs\_test>php f2-isset-2.php $arr[0] は宣言されています。 $arr[1] は宣言されていないか null です。 $arr["key1"] は宣言されています。 $arr["key0"] は宣言されていないか null です。 $arr["key2"]["test"] は宣言されています。 $arr["key2"]["test1"] は宣言されていないか null です。 $arr["key2"]["test"] は宣言されていないか null です。
■isset関数を使った例(HTMLのFORMタグでのPOST送信)
isset 関数を使用する例ですが以下の様な、 HTMLページの中に TEXTBOX を設置し SUBMIT ボタンで POST送信する時のデータ取得があります。 POST送信で PHP 側での受け取りは $_POST 変数から行います。
isset で $_POST をチェックするのは、最初にこのスクリプトが呼ばれた場合と、 SUBMIT ボタンを押下することで自分自身を呼出した場合の仕訳を行うためです。
最初にこのスクリプトが呼ばれた場合 $_POST にはデータが存在しませんが、 SUBMIT ボタンを押下した場合に from タグの中身が自分自身にPOSTされてきます。 それで isset でチェックしてデータを取得しています。<?php /* f2-isset-3.php */ // 受信データ変数初期化 $strName = ""; $strZipno = ""; $strAddr = ""; // $POSTから取得 if((isset($_POST['pname']) == true) && ($_POST['pname'] != "")){ $strName = trim($_POST['pname']); } if((isset($_POST['zipno']) == true) && ($_POST['zipno'] != "")){ $strZipno = trim($_POST['zipno']); } if((isset($_POST['addr']) == true) && ($_POST['addr'] != "")){ $strAddr = trim($_POST['addr']); } ?> <html> <head> <meta charset="utf-8"> <title>問合せ・個人情報</title> </head> <body> <h1>問合せ・個人情報</h1> <form name="enqform" action="enq1.php" method="post"> 名前 :<input type="text" name="pname" maxlength="20" value="<?php echo $strName; ?>" /><br /> 郵便番号:<input type="text" name="zipno" maxlength="8" value="<?php echo $strZipno; ?>" /><br /> 住所 :<input type="text" name="addr" maxlength="30" value="<?php echo $strAddr; ?>" /><br /> <input type="submit" value="送信" /> </form> </body> </html>
■unset関数
unset 関数ですが以下の様な定義になっています。
unset ( mixed $var , mixed ...$vars ) : void [説明] unset() は指定した変数を破棄します。 [パラメータ ] $var :破棄する変数。 $vars :その他のチェック対象変数。
以下にunset 関数を使用した例のスクリプトを示します。
<?php /* f2-unset-1.php */ // Windowsコマンドプロンプトで[XAMPP]のPHPで表示を Shift-JIS にする為の設定 ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // 変数宣言 $data = "111"; // 変数チェック if (isset($data) == true) { echo '$data は宣言されています。'."\n"; } else { echo '$data は宣言されていないか null です。'."\n"; } // 変数廃棄 unset($data); // 変数チェック if (isset($data) == true) { echo '$data は宣言されています。'."\n"; } else { echo '$data は宣言されていないか null です。'."\n"; } ?>
これをWindowsコマンドプロンプトで実行すると以下の表示になります。
C:\xampp\htdocs\_test>php f2-unset-1.php $data は宣言されています。 $data は宣言されていないか null です。
尚、unset 関数は配列の要素に対しても廃棄処理ができますので、その例としてのスクリプトを示します。
<?php /* f2-unset-2.php */ // 配列を宣言 $arr = array(0 => "11111", // KEY:数値 1 => "aaaaa", // KEY:数値 "key1" => "22222", // KEY:文字列 "key2" => array("test1" => "abcdef", // KEY:文字列で入れ子で複数配列 "test2" => "wwwwww"), "key3" => array("test" => "abcdef")); // KEY:文字列で入れ子で配列 // 最初に変数内部表示 print_r($arr); // 数値キーの廃棄 unset($arr[1]); // 文字列キーの廃棄 unset($arr["key1"]); // 子配列の廃棄1 unset($arr["key2"]["test1"]); // 子配列の廃棄2 unset($arr["key3"]["test"]); // 変数内部表示 print_r($arr); ?>
これをWindowsコマンドプロンプトで実行すると以下の表示になります。
C:\xampp\htdocs\_test>php f2-unset-2.php Array ( [0] => 11111 [1] => aaaaa [key1] => 22222 [key2] => Array ( [test1] => abcdef [test2] => wwwwww ) [key3] => Array ( [test] => abcdef ) ) Array ( [0] => 11111 [key2] => Array ( [test2] => wwwwww ) [key3] => Array ( ) )
配列の中の対応するキー値が削除されているのが分かると思います。
-
今回から PHP の標準関数の中で私が良く使うものを選んで、説明していきたいと思います。
その最初として文字列の分解・結合を行う関数である explode 及び implode を取り上げます。
■explode関数
先ずは explode 関数ですが以下の様な定義になっています。(PHP の正式な説明サイトより)
explode ( string $separator , string $string [, int $limit = PHP_INT_MAX ] ) : array [説明] 文字列の配列を返します。この配列の各要素は、 string を文字列 separator で区切った部分文字列となります。 [パラメータ ] $separator :区切り文字列。 $string :入力文字列。 $limit :limit に正の値が指定された場合、返される配列には 最大 limit の要素が含まれ、 その最後の要素には string の残りの部分が全て含まれます。 limit パラメータが負の場合、 最後の -limit 個の要素を除く全ての構成要素が返されます。 limit パラメータがゼロの場合は、1 を指定したものとみなされます。
それでは、簡単な文字列の分割について、以下にスクリプトを示します。 (尚、3行目の設定はWindowsコマンドプロンプトでの実行時に、コンソールへの出力を Shift-JIS にする為のものです)<?php /* f1-explode.php */ // Windowsコマンドプロンプトで[XAMPP]のPHPで表示を Shift-JIS にする為の設定 ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // 分割する文字列 $str = "東京,名古屋,京都,大阪"; // 分割処理 $arr = explode(",", $str); // 配列の内容表示 print_r($arr); </html>
これをWindowsコマンドプロンプトで実行すると以下の表示になります。
C:\xampp\htdocs\_test>php f1-explode.php Array ( [0] => 東京 [1] => 名古屋 [2] => 京都 [3] => 大阪 )
変数「$arr」に指標「0」から順にカンマで分割された文字列が設定されています。
それでは分割対象の文字列にカンマ(,)が無い場合と、関数の第3引数の「$limit」に指定を行う場合について例を示します。<?php /* f1-explode-2.php */ // Windowsコマンドプロンプトで[XAMPP]のPHPで表示を Shift-JIS にする為の設定 ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // 分割する文字列(カンマが無い) $str = "東京名古屋京都大阪"; // 分割処理 $arr = explode(",", $str); // 配列の内容表示 print_r($arr); // 分割する文字列 $str = "東京,名古屋,京都,大阪"; // 分割処理 $arr = explode(",", $str, 2); // limit:2 を設定 // 配列の内容表示 print_r($arr); </html>
これをWindowsコマンドプロンプトで実行すると以下の表示になります。
C:\xampp\htdocs\_test>php f1-explode-2.php Array ( [0] => 東京名古屋京都大阪 ) Array ( [0] => 東京 [1] => 名古屋,京都,大阪 )
分割文字列の中にカンマが無い場合は配列の指標「0」に分割指定文字列そのものが設定されます。
(区切り文字列に分割文字列に存在しないものを指定した場合や、NULL文字列でも同様となります。)
また、「$limit」が分割文字列のカンマの数より小さい場合は配列の指標「$limit - 1」の要素に残りの文字列が設定されます。
■implode関数
implode 関数ですが以下の様な定義になっています。
implode ( string $glue , array $pieces ) : string [説明] 配列の要素を glue 文字列で連結した文字列を返します。 [パラメータ ] $glue :連結する文字列。 $pieces :連結したい文字列の配列。
以下にimplode 関数を使用した例のスクリプトを示します。
<?php /* f1-implode.php */ // Windowsコマンドプロンプトで[XAMPP]のPHPで表示を Shift-JIS にする為の設定 ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // 連結する配列 $arr = array("東京", "名古屋", "京都", "大阪"); // 連結処理(カンマで連結) $str = implode(",", $arr); // 文字列の内容表示 echo "カンマで連結 [" . print_r($str, true) . "]\n"; // 連結処理(長い文字列で連結) $str = implode("--", $arr); // 文字列の内容表示 echo "長い文字列で連結[" . print_r($str, true) . "]\n"; // 連結処理(空白文字列で連結) $str = implode("", $arr); // 文字列の内容表示 echo "空白文字列で連結[" . print_r($str, true) . "]\n"; // 空の配列 $arr = array(); // 連結処理(カンマで連結) $str = implode(",", $arr); // 文字列の内容表示 echo "空の配列を連結 [" . print_r($str, true) . "]\n"; ?>
これをWindowsコマンドプロンプトで実行すると以下の表示になります。
C:\xampp\htdocs\_test>php f1-implode.php カンマで連結 [東京,名古屋,京都,大阪] 長い文字列で連結[東京--名古屋--京都--大阪] 空白文字列で連結[東京名古屋京都大阪] 空の配列を連結 []
ここまでは、単に関数のテストを行った感じですので、これらを利用した関数のスクリプトで示します。
■explode, implode関数を使った関数の例
大した関数ではないのですが、日付チェック用の関数を作ってみました。
日付が正しければ、日付文字列を返し、エラーの場合は false を返す様になっています。<?php /* f1-sample.php */ // Windowsコマンドプロンプトで[XAMPP]のPHPで表示を Shift-JIS にする為の設定 ob_start(function($buf){ return mb_convert_encoding($buf, 'SJIS', 'UTF-8'); }); // ===== // 日付チェック // ===== // $date string :日付を表す文字列 // [返り値] :日付OKの場合は日付文字列で返し、NGの場合は false を返す // ===== function ChkDate($_date) { // ハイフン("-")をスラッシュ("/")に変換 $date = str_replace("-", "/", $_date); // 年月日を分割 $arr = explode("/", $date); // Y/m/d 形式?? if (isset($arr[0]) == true && isset($arr[1]) == true && isset($arr[2]) == true) { // intに変換して "Y-n-j" 形式にする $intYY = intval($arr[0]); $intMM = intval($arr[1]); $intDD = intval($arr[2]); // 日付チェック if (checkdate($intMM, $intDD, $intYY) == true) { // 日付OKの場合[Y/n/j]書式で返す return implode("/", $arr); //以下の処理の方がいいかもしれません //$strDate = "{$intYY}-{$intMM}-{$intDD}"; //return date("Y/n/j", strtotime($strDate)); } } // エラーの場合は[false]を返す return false; } // [ChkDate]を使う関数 function ExcChkDate($strDate) { $ret = ChkDate($strDate); if ($ret === false) { echo $strDate."...error\n"; } else { echo $strDate." => ".$ret."...OK\n"; } } // OKの日付 ExcChkDate("2020/12/01"); // NGの日付 ExcChkDate("2019/02/29"); // 書式NGの日付 ExcChkDate("201902/29"); // 書式NGの日付 ExcChkDate("/02/29"); ?>
これをWindowsコマンドプロンプトで実行すると以下の表示になります。
C:\xampp\htdocs\_test>php f1-sample.php 2020/12/01 => 2020/12/01...OK 2019/02/29...error 201902/29...error /02/29...error
-
Webサイトの 問合せフォーム などでいろんな項目を入力して問合せを行うわけですが、 電話番号や郵便番号などで半角文字しか受け付けないページをたまに見かけます。
番号入力のテキストボックスで、入力時にIMEがONの状態で全角文字の数字をいれて、フォームの登録ボタンを押下すると 「半角文字の数字で入力して下さい。」などとエラーメッセージが表示されます。
必要な情報は半角文字なので PHP には全角から半角への変換ができる mb_convert_kana 関数があるので、 これを使ってできる限り欲しいデータに変換するべきだと思います。
(ただし、住所などの場合、全角と半角の混在が必要なときもあるので、強制的に半角⇒全角の変換はそれぞれのシステムによるとは思います)
それでは、簡単な 問合せフォーム を作成しましたので、以下にスクリプトを示します。
このスクリプトは以下の様な構成になっています。- $_POST から受け取る各データ変数の宣言を行う。
- $_POST から各データを取得する。
- 各データのエラーチェックを行う。
- HTML内でエラーメッセージがあれば表示を行う。
- FORMタグ内で各入力データの表示を行う。
<?php // 初期化 $strName = ""; $strZipno = ""; $strAddr = ""; $strTelno = ""; // $POSTから取得 if((isset($_POST['pname'])== true) && ($_POST['pname'] != "")){ $strName = trim($_POST['pname']); } if((isset($_POST['zipno'])== true) && ($_POST['zipno'] != "")){ $strZipno = trim($_POST['zipno']); } if((isset($_POST['addr'])== true) && ($_POST['addr'] != "")){ $strAddr = trim($_POST['addr']); } if((isset($_POST['telno'])== true) && ($_POST['telno'] != "")){ $strTelno = trim($_POST['telno']); } // エラーチェック $strErr = ""; // 名前 if ($strName == "") { $strErr .= "名前を入力して下さい。<br />"; } // 郵便番号 if ($strZipno == "") { $strErr .= "郵便番号を入力して下さい。<br />"; } else { // 郵便番号チェック(数字3桁または、数字3桁-4桁) if(!preg_match('/^([0-9]{3})(-[0-9]{4})?$/i', $strZipno)){ $strErr .= $strZipno.'は不正な郵便番号です。<br />'; } } // 住所 if ($strAddr == "") { $strErr .= "住所を入力して下さい。<br />"; } // 電話番号 if ($strTelno == "") { $strErr .= "電話番号を入力して下さい。<br />"; } else { // 電話番号チェック(数字のみのチェック) if(!preg_match('/^[0-9]+$/i', $strTelno)){ $strErr .= $strTelno.'は不正な電話番号です。<br />'; } } ?> <html> <head> <meta charset="utf-8"> <title>問合せ・個人情報</title> </head> <body> <h1>問合せ・個人情報</h1> <?php // エラーメッセージ処理 if ($strErr != "") { ?> <div id="ErrorMessage" style="color:red"> <h2>エラーメッセージ</h2> <p> 以下のエラーがあります!<br /> <?php echo $strErr; ?> </p> </div> <?php } ?> <form name="enqform" action="enq1.php" method="post"> 名前 :<input type="text" name="pname" maxlength="20" value="<?php echo $strName; ?>" /><br /> 郵便番号:<input type="text" name="zipno" maxlength="8" value="<?php echo $strZipno; ?>" /><br /> 住所 :<input type="text" name="addr" maxlength="30" value="<?php echo $strAddr; ?>" /><br /> 電話番号:<input type="text" name="telno" maxlength="13" value="<?php echo $strTelno; ?>" /><br /> <input type="submit" value="送信" /> </form> </body> </html>
エラーが表示される様なデータを入力し「送信」ボタンを押下すると以下の表示になります。
「郵便番号」「電話番号」には全角の数字を入力しましたので、エラーメッセージが表示されます。
尚、このスクリプトは最初に表示した時に全ての項目の未入力エラーが表示されます。 これの解消は、自分自身で処理モードを持って最初の表示なのか、「送信」ボタンを押下した時なのかを判定する必要があります。
■全角文字を半角文字に変換する処理を追加したスクリプト
最初にもありましたが mb_convert_kana 関数を使って必要な個所で全角文字を半角文字に変換を行います。
mb_convert_kana 関数ですが以下の様な定義になっています。mb_convert_kana ( string $str [, string $option = "KV" [, string $encoding = mb_internal_encoding() ]] ) : string $str :変換される文字列。 $option :変換オプションで以下の組み合わせで行う。 ・"r" 「全角」英字を「半角」に変換します。 ・"R" 「半角」英字を「全角」に変換します。 ・"n" 「全角」数字を「半角」に変換します。 ・"N" 「半角」数字を「全角」に変換します。 ・"a" 「全角」英数字を「半角」に変換します。 ・"A" 「半角」英数字を「全角」に変換します。 ("a", "A" オプションに含まれる文字は、U+0022, U+0027, U+005C, U+007Eを除く U+0021 - U+007E の範囲です) ・"s" 「全角」スペースを「半角」に変換します(U+3000 -> U+0020)。 ・"S" 「半角」スペースを「全角」に変換します(U+0020 -> U+3000)。 ・"k" 「全角カタカナ」を「半角カタカナ」に変換します。 ・"K" 「半角カタカナ」を「全角カタカナ」に変換します。 ・"h" 「全角ひらがな」を「半角カタカナ」に変換します。 ・"H" 「半角カタカナ」を「全角ひらがな」に変換します。 ・"c" 「全角カタカナ」を「全角ひらがな」に変換します。 ・"C" 「全角ひらがな」を「全角カタカナ」に変換します。 ・"V" 濁点付きの文字を一文字に変換します。"K", "H" と共に使用します。 $encoding:文字エンコーディングを指定します。省略した場合は、 内部文字エンコーディングを使用します。
今回の電話番号、郵便番号は mb_convert_kana 関数のオプション指定は「全角」英数字を「半角」に変換する "a" となります。
あと一つ問合せフォームなどの入力値の扱いで重要なことがあります。
それは、POSTされてきた値をそのまま input タグの value に設定しないことです。
クロスサイトスクリプトの攻撃を防ぐためには必要です。
これを防ぐためには入力値を htmlspecialchars 関数で特殊文字を HTML エンティティに変換します。
関数には引数が必要なので、ラッパ関数として function h() を宣言しそれを使用します。
以下に改良したスクリプトを示します。<?php // 特殊文字を HTML エンティティに変換する関数 function h($s) { return htmlspecialchars($s, ENT_QUOTES, "UTF-8"); } // 処理モード define('MODE_NEW', 1); // 新規 define('MODE_REG', 2); // 登録 // 初期化 $intMode = 0; $strName = ""; $strZipno = ""; $strAddr = ""; $strTelno = ""; // $POSTから取得 if((isset($_POST['mode'])== true) && ($_POST['mode'] != "")){ $intMode = intval($_POST['mode']); } if ($intMode == 0) { $intMode = MODE_NEW; } if((isset($_POST['pname'])== true) && ($_POST['pname'] != "")){ $strName = trim($_POST['pname']); } if((isset($_POST['zipno'])== true) && ($_POST['zipno'] != "")){ $strZipno = trim($_POST['zipno']); $strZipno = mb_convert_kana($strZipno, "a"); // 「全角」⇒「半角」変換 } if((isset($_POST['addr'])== true) && ($_POST['addr'] != "")){ $strAddr = trim($_POST['addr']); } if((isset($_POST['telno'])== true) && ($_POST['telno'] != "")){ $strTelno = trim($_POST['telno']); $strTelno = mb_convert_kana($strTelno, "a"); // 「全角」⇒「半角」変換 } // エラーチェック $strErr = ""; if ($intMode == MODE_NEW) { // 新規モードの場合は、登録モードにする $intMode = MODE_REG; } else if ($intMode == MODE_REG) { // 名前 if ($strName == "") { $strErr .= "名前を入力して下さい。<br />"; } // 郵便番号 if ($strZipno == "") { $strErr .= "郵便番号を入力して下さい。<br />"; } else { // 郵便番号チェック(数字3桁または、数字3桁-4桁) if(!preg_match('/^([0-9]{3})(-[0-9]{4})?$/i', $strZipno)){ $strErr .= $strZipno.'は不正な郵便番号です。<br />'; } } // 住所 if ($strAddr == "") { $strErr .= "住所を入力して下さい。<br />"; } // 電話番号 if ($strTelno == "") { $strErr .= "電話番号を入力して下さい。<br />"; } else { // 電話番号チェック(数字のみのチェック) if(!preg_match('/^[0-9]+$/i', $strTelno)){ $strErr .= $strTelno.'は不正な電話番号です。<br />'; } } } ?> <html> <head> <meta charset="utf-8"> <title>問合せ・個人情報</title> </head> <body> <h1>問合せ・個人情報</h1> <?php // エラーメッセージ処理 if ($strErr != "") { ?> <div id="ErrorMessage" style="color:red"> <h2>エラーメッセージ</h2> <p> 以下のエラーがあります!<br /> <?php echo $strErr; ?> </p> </div> <?php } ?> <form name="enqform" action="enq2.php" method="post"> 名前 :<input type="text" name="pname" maxlength="20" value="<?php echo h($strName); ?>" /><br /> 郵便番号:<input type="text" name="zipno" maxlength="8" value="<?php echo h($strZipno); ?>" /><br /> 住所 :<input type="text" name="addr" maxlength="30" value="<?php echo h($strAddr); ?>" /><br /> 電話番号:<input type="text" name="telno" maxlength="13" value="<?php echo h($strTelno); ?>" /><br /> <input type="hidden" name="mode" value="<?php echo $intMode; ?>" /><br /> <input type="submit" value="送信" /> </form> </body> </html>
尚、 htmlspecialchars 関数は以下の様に定義されています。
htmlspecialchars ( string $string [, int $flags = ENT_COMPAT [, string|null $encoding = NULL [, bool $double_encode = TRUE ]]] ) : string $string 変換される文字列。 $flags 以下のフラグを組み合わせたビットマスクです。 クォートや無効な符号単位シーケンス、そして文書型の扱いを指定します。 デフォルトは ENT_COMPAT | ENT_HTML401 です。 ・ENT_COMPAT ダブルクオートは変換しますがシングルクオートは変換しません。 ・ENT_QUOTES シングルクオートとダブルクオートを共に変換します。 ・ENT_NOQUOTES シングルクオートとダブルクオートは共に変換されません。 ・ENT_SUBSTITUTE 無効な符号単位シーケンスを含む文字列を渡したときに、 空の文字列を返すのではなく Unicode の置換文字に置き換えます。 (UTF-8 の場合は U+FFFD、それ以外の場合は � となります) ・ENT_DISALLOWED 指定した文書型において無効な符号位置を、 Unicode の代替文字である U+FFFD (UTF-8) あるいは � で置き換えます。 これを設定しなければ、無効な符号位置をそのまま残します。 これは、外部コンテンツを埋め込んだ XML 文書を整形式に保つために有用です。 ・ENT_HTML401 コードを HTML 4.01 として処理します。 ・ENT_XML1 コードを XML 1 として処理します。 ・ENT_XHTML コードを XHTML として処理します。 ・ENT_HTML5 コードを HTML 5 として処理します。 $encoding オプションの引数。文字を変換するときに使うエンコーディングを定義します。
上記のスクリプトはまだまだ突っ込みどころ満載で以下の様な処理が必要かと思われますので、 皆さんで追加して下さい。- 問合せの内容を登録する処理。(データベースに依存)
- 登録後の処理をどうするのか。(「登録しました」等のメッセージ表示?)
- 電話番号のエラーチェックが甘い。
- 住所の情報は1個で良いのか。(データベース・テーブルに依存)
- 現状メールアドレスはありませんが、メールアドレスへの確認送信。
- ブラウザのページ戻りの処理をどうするのか?
-
以前 Javascript の以下の記事で QR-CODE の表示を説明しました。
⇒ JavaScript jQueryでQRコードを表示する方法
そこで今回は PHP で作成されたライブラリを使う方法で行ってみます。
このライブラリですが、以下のページからダウンロードできます。
⇒QRcode Perl/CGI & PHP scripts ver. 0.50j
「QRcode Perl CGI & PHP scripts ver. 0.50j ( 2013/5/18)」の「qr_img0.50j.tar.gz (1007KB) 」をダウンロードします。
ダウンロード後は以下の様に展開します。- [qr_img0.50j.tar.gz]ファイルを解凍 ⇒ [qr_img0.50j.tar]ができる。
- [qr_img0.50j.tar]ファイルを解凍 ⇒ [qr_img0.50j]フォルダへのソース展開される。
- [qr_img0.50j]フォルダの中の[qr_img0.50j]フォルダを自分の使用する適当なフォルダにコピーする。
このライブラリは「Y.Swetake」さんが作成されたもので、 「これらのプログラムの著作権は作者であるY.Swetakeにあります。 これらのプログラムはフリーウエアです。もとの著作権表示を変更しなければ 自由に再配布・改造してもかまいません。」とのことです。
それでは、このライブラリの使い方を説明します。使用方法は HTML の IMG タグに以下の様に記述します。<img src="xxx/qr_img0.50j/php/qr_img.php?d=data[&e=(L,M,Q,H)][&s=int size][&v=(1-40)][&t=J]"> ・d:コード変換する文字列(特殊文字や8bit文字はURLencodeされている必要があります) ・e:エラー訂正レベル(指定できるのはL,M,Q,Hの4種類で省略した場合 M が選択されます) ・s:モジュールサイズ(指定できるのは1以上の整数,省略した場合 4(png) または 8(jpeg) ) ・v:バージョン(1~40,省略した場合はプログラムが自動選択) ・t:画像タイプ(J:Jpeg、省略した場合は PNG) xxx:「qr_img0.50j」フォルダが存在する上位のフォルダ
尚、指定するパラメータは「d」「s」だけで問題無いと思います。
■QR-CODEを表示するPHPスクリプト
以下にスクリプトを示します。
<?php $strQR1en = urlencode("Test QR-Code"); $strQR2 = "Test QR-Code 0123456789 abcdefghijklmnopqrstuvwxyz"; $strQR2en = urlencode($strQR2); ?> <html> <head> <meta charset="utf-8"> <title>Test QR-Code</title> </head> <body> <h1>Test QR-Code</h1> <br />size=4<br /> <img src="./qr_img0.50j/php/qr_img.php?s=4&d=<?php echo $strQR1en; ?>"> <br />size=5<br /> <img src="./qr_img0.50j/php/qr_img.php?s=5&d=<?php echo $strQR1en; ?>"> <br />size=6<br /> <img src="./qr_img0.50j/php/qr_img.php?s=6&d=<?php echo $strQR1en; ?>"> <br />size=6 [<?php echo $strQR2; ?>]<br /> <img src="./qr_img0.50j/php/qr_img.php?s=6&d=<?php echo $strQR2en; ?>"> </body> </html>
以下に実行結果を示します。