Edited at

【PHP入門講座】 想定外の入力への対応

More than 5 years have passed since last update.


目次に戻る


想定外の入力でエラーが発生するケース

まずは名前を「test」として、 welcome.php を実行しましょう。現在アドレスバーに表示されているURLは

http://localhost/welcome.php?my_name=test

という形になっていると思います。今回はここから色々いじってみます。


1. welcome.php に直接アクセスされたとき


問題の発生

アドレスバーのURLを http://localhost/welcome.php にして直接アクセスしてみましょう。

こんにちは、

Notice: Undefined index: my_name in C:\xampp\htdocs\welcome.php on line 20
さん!

という Notice(通知) が発生するはずです。これは7行目、

<p>こんにちは、<?=h($_GET['my_name'])?>さん!</p>

において、 $_GET['my_name'] が未定義(Undefined)だよ! という意味のエラーです。URLからパラメータ my_name を削ってしまったので、この変数が存在しなくなってしまったのです。


解決策

isset 構文を使って、 $_GET['my_name'] が定義されているかどうか確認します。ここで if else 文が初登場しますが、

if (/* 条件式 */) {

// 条件式が成立するとき
} else {
// 条件式が成立しないとき
}

というように条件分岐させるためのものだと思ってください。

以下のように welcome.php の書き換えを行ってください。

<?php

/**
* HTML特殊文字をエスケープする関数
*/
function h($str) {
return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
}

// $_GET['my_name'] が定義されているかどうか調べる
if (isset($_GET['my_name'])) {
// 定義されていればそのまま$my_nameに代入
$my_name = $_GET['my_name'];
} else {
// 未定義ならば「名無し」として設定
$my_name = '名無し';
}

// Content-Typeヘッダー送信
header('Content-Type: application/xhtml+xml; charset=utf-8');

?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja">
<head>
<title>Hello!!</title>
</head>
<body>
<p>こんにちは、<?=h($my_name)?>さん!</p>
</body>
</html>


確認

もう一度直接アクセスを行い、「こんにちは、名無しさん!」と表示されれば成功です。


2. welcome.phpmy_name が配列として渡されたとき


問題の発生

アドレスバーのURLを http://localhost/welcome.php?my_name[a]=b にして直接アクセスしてみましょう。

こんにちは、

Warning: htmlspecialchars() expects parameter 1 to be string, array given in C:\xampp\htdocs\welcome.php on line 7
さん!

という Warning(警告) が発生するはずです。これは20行目、

return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');

において、 第1引数 $str が文字列じゃないといけないのに配列が渡されたよ! という意味のエラーです。配列に関しては後で詳しく学習しますが、イメージとしては最初述べたように箱に例えるならば 「重箱」 に相当します。この例では、

$str['a'] = 'b';

のような形で受け取ってしまっており、 「str」という箱の中にある「a」という箱の中の値が「b」 という状況を示しています。 htmlspecialchars 関数は配列を処理することが出来ないので、このエラーを発生しています。


解決策

is_string 関数を使って、 $_GET['my_name']文字列(String) になっているかどうか確認します。

ここで論理演算子 && が初登場しますが、日本語に直訳すると 「且つ」 を意味します。

以下のように welcome.php の書き換えを行ってください。

<?php

/**
* HTML特殊文字をエスケープする関数
*/
function h($str) {
return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
}

// $_GET['my_name'] が定義されており、且つ文字列であるかどうか調べる
if (isset($_GET['my_name']) && is_string($_GET['my_name'])) {
// 定義されていて文字列であればそのまま$my_nameに代入
$my_name = $_GET['my_name'];
} else {
// 未定義か配列ならば「名無し」として設定
$my_name = '名無し';
}

// Content-Typeヘッダー送信
header('Content-Type: application/xhtml+xml; charset=utf-8');

?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja">
<head>
<title>Hello!!</title>
</head>
<body>
<p>こんにちは、<?=h($my_name)?>さん!</p>
</body>
</html>


確認

もう一度直接アクセスを行い、「こんにちは、名無しさん!」と表示されれば成功です。


エラーは発生しないが想定外の入力として処理したいケース


3. 名前が空欄で送信されたとき


問題の発生

form.php から名前が空欄のまま送信してみましょう。

こんにちは、さん!

このときにもぜひ「名無しさん」と表示させたいですよね。


解決策

!== 演算子を使って、 $_GET['my_name']空欄(空文字列) になっていないかどうか確認します。

以下のように welcome.php の書き換えを行ってください。

<?php

/**
* HTML特殊文字をエスケープする関数
*/
function h($str) {
return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
}

if (
isset($_GET['my_name']) && // $_GET['my_name'] が定義されており、
is_string($_GET['my_name']) && // 且つ文字列であり、
$_GET['my_name'] !== '' // 且つ空欄でないかどうか調べる
) {
// 条件をすべて満たせばそのまま$my_nameに代入
$my_name = $_GET['my_name'];
} else {
// 1つでも満たさないものがあれば「名無し」として設定
$my_name = '名無し';
}

// Content-Typeヘッダー送信
header('Content-Type: application/xhtml+xml; charset=utf-8');

?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja">
<head>
<title>Hello!!</title>
</head>
<body>
<p>こんにちは、<?=h($my_name)?>さん!</p>
</body>
</html>


確認

もう一度空欄にして送信を行い、「こんにちは、名無しさん!」と表示されれば成功です。