LoginSignup
20

More than 5 years have passed since last update.

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

Last updated at Posted at 2013-11-25

目次に戻る

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

まずは名前を「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>

確認

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

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
20