掲示板を作成
トップページ
- 掲示板へのリンクを作る
《index.php》
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>テニスサークル交流サイト</title> </head> <body> <h1>テニスサークル交流サイト</h1> <p><a href="album.php">アルバム</a></p> <p><a href="bbs.php">掲示板</a></p> <h2>お知らせ</h2> </body> </html>
入力フォームの作成
《bbs.php》
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>交流サイト:掲示板</title> </head> <body> <h1>掲示板</h1> <form action="write.php" method="post"> <p>名前:<input type="text" name="name"></p> <p>タイトル:<input type="text" name="title"></p> <textarea name="body"></textarea> <p>削除パスワード(数字4桁):<input type="text" name="pass"></p> <p><input type="submit" value="書き込む"></p> </form> <p><a href="index.php">トップページに戻る</a></p> </body> </html>
データベース書き込みプログラム
- bbs.phpで入力されたデータを受信し、入力項目のうちの必須項目(名前、本文)がきちんと記入されているか調べます
- 入力漏れがなければデータベースに接続し、テーブルにレコードを追加します
- この場合、エラー時にbbs.phpに戻すではわかりにくいので、index.phpに戻す設定にしています
《write.php》
<?php // データの受け取り $name = $_POST['name']; $title = $_POST['title']; $body = $_POST['body']; $pass = $_POST['pass']; // 必須項目チェック(名前か本文が空ではないか?) if ($name == '' || $body == ''){ header('Location: index.php'); // index.phpへ移動 exit(); // 終了 } // 必須項目チェック(パスワードは4桁の数字か?) if (!preg_match("/^[0-9]{4}$/", $pass)){ header('Location: index.php'); exit(); } // データベースに接続 $dsn = 'mysql:host=localhost;dbname=tennis;charset=utf8'; $user = 'tennisuser'; $password = 'xxxxxxxx'; // tennisuserに設定したパスワード try { $db = new PDO($dsn, $user, $password); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); // プリペアドステートメントを作成 $stmt = $db->prepare(" INSERT INTO bbs (name, title, body, date, pass) VALUES (:name, :title, :body, now(), :pass)" ); // パラメータを割り当て $stmt->bindParam(':name', $name, PDO::PARAM_STR); $stmt->bindParam(':title', $title, PDO::PARAM_STR); $stmt->bindParam(':body', $body, PDO::PARAM_STR); $stmt->bindParam(':pass', $pass, PDO::PARAM_STR); // クエリの実行 $stmt->execute(); // index.phpに戻る header('Location: index.php'); exit(); } catch(PDOException $e) { die ('エラー:' . $e->getMessage()); }
- 投稿後のデータベースの表示
必須項目のチェック
POSTメソッドでデータを受け取る
<?php // データの受け取り $name = $_POST['name']; $title = $_POST['title']; $body = $_POST['body']; $pass = $_POST['pass'];
名前と本文のチェック
- 必須項目のチェック
- isset() あるかどうか
- empty() 無いかどうか
指定したURLへジャンプする
header ( 'Location: 戻り先のURL' );
- headerは、HTTPヘッダを送信するための関数
- 他のページへのジャンプを指示する情報
- 「bbs.php」に戻す
サーバーとデータベースの指定
- データベースに接続するときに必要な DSN とユーザー名、パスワードです
<?php // データベースに接続 $dsn = 'mysql:host=localhost; dbname=tennis; charset=utf8'; $user = 'tennisuser'; $password = 'password'; // tennisuserに設定したパスワード
DSN(Data Source Name)
- DSNとは、どのサーバーにあるどんなデータベースを使うのかを指定した文字列のこと
mysql: host=ホスト名; dbname=データベース名; charset=文字コード
例外処理
- 「try-catch」は、例外処理のための構文です
- 「try-catch」で例外の処理をしなかったら、例外が発生した段階でプログラムが止まってしまい、期待通りにその後の処理が実行されません
- このプログラムの場合、PDOException という種類の例外が発生したときのみ、catchの中の処理が実行されます
<?php try { $db = new PDO($dsn, $user, $password); (略) } catch(PDOException $e) { die ('エラー:' . $e->getMessage()); }
- 例外が発生しそうな処理を「try」の中に入れておく
- 例外が発生すると Exception を投げる(Throw する)
- 例外を catch すると、catch 内の処理を実行する
PDO(PHP Data Objects)
- PDOとは、さまざまなデータベースを簡単に利用できるようにする、PHPの拡張機能です
- PHPとDBMSの間に「抽象化レイヤー」を挟んで各種DBMSの違いをこのレイヤーで吸収し、異なるDBMS に対して同じプログラムで同じ処理をできるようにする
- 抽象化レイヤーには、PDO(PHPプログラムで使うデータベース接続の機能)と、PDOが使う各種DBMS用ドライバ(DBMSとPDOをつなぐ機能)が含まれています
- しかし、ドライバを意識する必要はない
$db = new PDO($dsn, $user, $password);
オブジェクト指向
$db = new PDO($dsn, $user, $password); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
- new演算子を使ってPDOクラスのインスタンスを作成しています
- PDOクラスは、インスタンスを作る際に引数にDSN、ユーザー名、パスワードを必要とします
- setAttributeは、プリペアドステートメントを使う際にセキュリティを高めるために設定します
- MySQL を PDO で使うときは ATTR_EMULATE_PREPARES を設定しよう
プリペアドステートメント(テンプレート)
- プリペアドステートメントは、PDOインスタンスのメソッドを実行するための構文
- PDOのインスタンスである $db が持っている、prepare というメソッドを実行します
- メソッドは、オブジェクトが持つ関数のようなもので、アロー演算子(->)で「このオブジェクトのこの関数を使う」ということを明示的に表します
- プリペアドステートメントとは、実行したいクエリのテンプレートのようなものです
- 「:名前」の部分に、bindParamメソッドで後から値を埋め込みます
- 後から値を埋め込む「:〜」の部分のことをプレースホルダーと呼びます
$db->prepare( "ステートメント文字列" );
$stmt = $db->prepare("
INSERT INTO bbs (name, title, body, date, pass)
VALUES (:name, :title, :body, now(), :pass)"
);
INSERT 文によるレコード追加
- INSERT 文は、テーブルに新しいレコードを追加するSQLの構文です
- nameやtitleのように文字列を値としたときに、通常クォーテーションで文字列を囲む必要がありますが、プリペアドステートメント使う場合は、自動的にクォーテーションをつけてくれるため不要です
- dateは、日付時刻を指定するカラムですが、now() を指定しておくとレコード追加時に自動で日付時刻に展開してくれます
- now() は、MySQLの持つ現在日時を表す関数を呼び出しています
INSERT INTO テーブル名 (カラム1, カラム2, カラム3, ・・・) VALUES (値1, 値2, 値3, ・・・)"
executeメソッド
- クエリの実行
$stmt->execute();
- クエリが終わったら、header関数を使って「bbs.php」へ戻す
header('Location: bbs.php');
個々までの例は、セキュリティ対策を簡略化しています。
外部に公開するには、セキュリティ対策が必須になります。