PHPによる入力データの検証(データバリデーション)
カテゴリ:PHP編
PHP+MySQLによる簡単なブログサイトの構築ではデータベース連携に主眼を置いて解説したため、入力データの検証(データバリデーション)は省略しましたが、この記事ではデータバリデーションを提供するクラスの作成について解説していきます。 クラスとして実装する理由は、データバリデーションは通常、同じバリデーション処理を複数のページ(記事登録・記事編集ページなど)で実施するためです。バリデーションクラスの作成
クラス名は DataValidation とします。
まず、ブログの登録時にはタイトル、本文、カテゴリーの入力があるため、$title、$text、$categoryを引数に取るバリデーションメソッドを作成します。 また、エラーメッセージを格納するためのインスタンス変数 $errorMsg を作成し、各バリデーションチェックメソッドに抵触した場合にエラーメッセージを保存するようにします。
例)
class DataValidation {
$errorMsg = "";
function validForArticleParams($title, $text, $category) {
//空文字のチェック
if ($title == "" || $text == "" || $category == "") {
$this->errorMsg = "入力されていない項目があります。";
return false;
}
//入力値の型のチェック
if (!is_string($title) || !is_string($text) || !is_string($category)) {
$this->errorMsg = "入力値が不正な項目があります。";
return false;
}
//入力値のサイズのチェク
if ($title > 100 || $text > 50000 || $category > 50) {
$this->errorMsg = "入力値のサイズが制限を超えている項目があります。";
return false;
}
return true;
}
}
また、ブログの更新時にはタイトル、本文、カテゴリーに加えてIDの入力もあるため、$idも引数に取る以下のバリデーションメソッドも作成します。
function validForArticleParamsWithId($id, $title, $text, $category) {
//空文字のチェック
if ($id == "") {
$this->errorMsg = "IDがありません。";
return false;
}
//入力値の型のチェック
if (!is_int($id)) {
$this->errorMsg = "IDの型が不正です。";
return false;
}
//入力値のサイズのチェク
if ($id > 1000000) {
$this->errorMsg = "IDのサイズが制限を超えています。";
return false;
}
//ID以外のバリデーションを実施
if($this->validForArticleParams($title, $text, $category)) {
return false;
};
return true;
}
最後にエラーメッセージ取得用のメソッド getErrorMsg() を追加し、最終的に DataValidation クラスは以下のようになります。
class DataValidation {
private $errorMsg = "";
function validForArticleParams($title, $text, $category) {
//空文字のチェック
if ($title == "" || $text == "" || $category == "") {
$this->errorMsg = "入力されていない項目があります。";
return false;
}
//入力値の型のチェック
if (!is_string($title) || !is_string($text) || !is_string($category)) {
$this->errorMsg = "入力値が不正な項目があります。";
return false;
}
//入力値のサイズのチェク
if ($title > 100 || $text > 50000 || $category > 50) {
$this->errorMsg = "入力値のサイズが制限を超えている項目があります。";
return false;
}
return true;
}
function validForArticleParamsWithId($id, $title, $text, $category) {
//空文字のチェック
if ($id == "") {
$this->errorMsg = "IDがありません。";
return false;
}
//入力値の型のチェック
if (!is_int($id)) {
$this->errorMsg = "IDの型が不正です。";
return false;
}
//入力値のサイズのチェク
if ($id > 1000000) {
$this->errorMsg = "IDのサイズが制限を超えています。";
return false;
}
//ID以外のバリデーションを実施
if($this->validForArticleParams($title, $text, $category)) {
return false;
};
return true;
}
//エラーメッセージの取得用メソッド
function getErrorMsg() {
return $this->errorMsg;
}
}
使い方
DataValidation クラスは以下のように使用します。
//クラスの読み込み
include("DataValidation.php");
//インスタンス化
$dv = new DataValidation();
//バリデーションチェック
if ($dv->validForArticleParams($title, $text, $category)) {
//バリデーション成功時の処理
} else {
//バリデーション失敗時の処理
echo $dv->getErrorMsg(); //エラーメッセージを表示
}
実際の実装例
では、PHP+MySQLによる簡単なブログサイトの構築で作成したブログ記事登録用ページ article_add.php とブログ記事編集用ページ article_modify.php に実際にバリデーションクラスを実装してみましょう。 以下のようになります。
article_add.php
<html>
<?php
//title、text、cateoryパラメータがPOSTメソッドで送られてきたら登録と判断
if (isset ($_POST['title']) && isset ($_POST['text']) && isset ($_POST['category']) ) {
$title = $_POST['title'];
$text = $_POST['text'];
$category = $_POST['category'];
include("DataValidation.php");
$dv = new DataValidation();
//バリデーション
if ($dv->validForArticleParams($title, $text, $category)) {
//データベース接続
$dsn = "mysql:host=localhost;dbname=blog";
$username = "root";
$password = "pass";
$db = new PDO($dsn, $username, $password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//category_listテーブルに同名のカテゴリーが存在しなければカテゴリーを登録
try {
$res = $db->query("SELECT COUNT(*) FROM category_list WHERE category = '" . $category . "'");
if ($res->fetchColumn() == 0) {
$statement = $db->prepare("INSERT INTO category_list (category) VALUES (:category)");
$statement->bindValue(':category', $category, PDO::PARAM_STR);
$statement->execute();
$statement = null;
echo "カテゴリーを追加しました。";
}
}
catch (Exception $error) {
echo "カテゴリーの登録失敗:" . $error->getMessage();
}
//記事を登録
try {
$statement = $db->prepare("INSERT INTO blog (title, text, date, category_id) VALUES (:title, :text, NOW(), (SELECT id FROM category_list WHERE category = :category))");
$statement->bindValue(':title', $title, PDO::PARAM_STR);
$statement->bindValue(':text', $text, PDO::PARAM_STR);
$statement->bindValue(':category', $category, PDO::PARAM_STR);
$statement->execute();
$statement = null;
echo "記事を追加しました。";
}
catch (Exception $error) {
echo "記事の登録失敗:" . $error->getMessage();
}
} else {
//バリデーション失敗
echo $dv->getErrorMsg();
}
} else { ?>
<!-- 記事の登録フォーム -->
<form name="artible_add" action="article_add.php" method="post">
<p>カテゴリ:<input name="category" type="text">
<p>タイトル:<input name="title" type="text">
<p>本文:<br><textarea name="text" cols="50" rows="10"></textarea>
<p><input type="submit" value="登録">
</form>
<?php } ?>
</html>
article_modify.php
<html>
<?php
//データベース接続
$dsn = "mysql:host=localhost;dbname=blog";
$username = "root";
$password = "pass";
$db = new PDO($dsn, $username, $password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//id、title、text、cateoryパラメータがPOSTメソッドで送られてきたら更新と判断
if (isset ($_POST['id']) && isset ($_POST['title']) && isset ($_POST['text']) && isset ($_POST['category'])) {
$id = $_POST['id'];
$title = $_POST['title'];
$text = $_POST['text'];
$category = $_POST['category'];
include("DataValidation.php");
$dv = new DataValidation();
//バリデーション
if ($dv->validForArticleParams($title, $text, $category, $id)) {
//category_listテーブルに同名のカテゴリーが存在しなければカテゴリーを登録
try {
$res = $db->query("SELECT COUNT(*) FROM category_list WHERE category = '" . $category . "'");
if ($res->fetchColumn() == 0) {
$statement = $db->prepare("INSERT INTO category_list (category) VALUES (:category)");
$statement->bindValue(':category', $category, PDO::PARAM_STR);
$statement->execute();
$statement = null;
echo "カテゴリーを追加しました。";
}
}
catch (Exception $error) {
echo "カテゴリーの登録失敗:" . $error->getMessage();
}
//記事を更新
try {
$statement = $db->prepare("UPDATE blog SET title = :title, text = :text, category_id = (SELECT id FROM category_list WHERE category = :category) WHERE id = :id");
$statement->bindValue(':title', $title, PDO::PARAM_STR);
$statement->bindValue(':text', $text, PDO::PARAM_STR);
$statement->bindValue(':category', $category, PDO::PARAM_STR);
$statement->bindValue(':id', $id, PDO::PARAM_INT);
$statement->execute();
$statement = null;
echo "記事を更新しました。";
}
catch (Exception $error) {
echo "記事の更新失敗:" . $error->getMessage();
}
} else {
//バリデーション失敗
echo $dv->getErrorMsg();
}
} else //idパラメータがGETメソッドで送られてきたら、該当idの記事データを取得してフォームに表示
if (isset ($_GET['id'])) {
$id = $_GET['id'];
$statement = $db->prepare("SELECT id, (SELECT category FROM category_list WHERE category_id = id) AS category, title, text, date FROM blog WHERE id = :id");
$statement->bindValue(':id', $id, PDO::PARAM_INT);
$statement->execute();
$row = $statement->fetch();
?>
<!-- 記事の更新フォーム -->
<form name="article_modify" action="article_modify.php" method="post">
<p>記事ID:<?php echo $row['id']; ?>
<p>カテゴリ:<input name="category" type="text" value="<?php echo $row['category']; ?>">
<p>タイトル:<input name="title" type="text" value="<?php echo $row['title']; ?>">
<p>本文:<br><textarea name="text" cols="50" rows="10"><?php echo $row['text']; ?></textarea>
<input name="id" type="hidden" value="<?php echo $row['id']; ?>">
<p><input type="submit" value="更新">
</form>
<?php } ?>
</html>
以上、PHPによる入力データの検証(データバリデーション)の解説でした。
公開日時:2020年06月12日 08:05:05
最終更新日時:2022年02月06日 20:36:35