簡易画像掲示板の構成とログイン


■作成する簡易画像掲示板の構成

単純なアップロード機能のみの簡易画像掲示板を作成します。

作成する簡易画像掲示板の主な機能です。

・あらかじめ登録されている4ユーザーだけがアクセス可能

JPEG画像とメッセージのみがアップロード可能

・画像一覧をサムネイルで表示し、サムネイルをクリックすると元画像を表示

ようするに画像とメッセージをアップするだけの簡単なものです。画像の種類もJPEGに限定しています。

しかし2つのテーブルと6つのPHPスクリプトを含むそれなりに長いプログラムです。

次は今回作成する簡易画像掲示板の構成です。

f:id:mkyosuke:20191209180235p:plain

f:id:mkyosuke:20191209180645p:plain

■データベースとテーブルの構成

次はこの簡易画像掲示板で使うテーブルの内容です。データベースはすでに作成済みの「db」を使用します。

●テーブル「table1」

「table1」は、次のようなカラム構造になっており、投稿番号や画像ファイル名とメッセージなどを保存するメインテーブルです。

テーブル「table1」の構造

カラム名 データ型 内容
ban int 投稿番号(連続番号機能)
nam varchar(128) 投稿者の名前
mes varchar(128) メッセージ
ope int 非公開なら「0」、公開なら「1」
gaz varchar(64) 画像ファイルの名前
dat datetime 投稿日時

●画像ファイルを保管するときのファイル名

アップロードされたファイルをWebサーバーに保存するとき、カラム「gaz」にはその画像ファイルの名前を保管します。この画像ファイルの名前は、処理した「年月日時分秒(date('YmdHis'))」に、アップロードしたときの「元のファイル名」を結合した文字列とします。

●サムネイル画像ファイルを保管するときのファイル名

サムネイル画像のファイルの名前は、保存した画像ファイル本体の名前に「xamp_」を付けた名前とします。たとえば、保管されるファイルの名前が「999999999abcdef.jpg」の場合、サムネイル画像のファイルの名前は「xamp_999999999abcdef.jpg」となります。

●テーブル「table2」

「table2」は、ユーザーの情報を格納するテーブルです。構造は、次のようになります。

テーブル「table2」の構造

カラム名 データ型 内容
id varchar(64) ユーザー名
pas varchar(64) パスワード(md5で処理したものを保管)
nam varchar(128) 会員氏名

このテーブルに以下のようなユーザーを登録します。

テーブル「table2」に登録するユーザー

id pas nam
admin himitunopass tanaka
user1 inupass dog
user2 nekopass cat
user3 usagipass rabbit

カラム「pas」にはパスワードの情報を保管しますが、そのままのパスワード文字列ではありません。それぞれのパスワードの文字列を引数としてmd5関数で処理した値を、カラム「pas」に保管するものとします。

●簡易画像掲示板作成上の注意

画像掲示板では、Cookieとセッションを使用します。たとえばCookieをブロックする設定になっていると、認証されても画像掲示板を利用することはできません。

サンプルを利用するときは、Cookieを「受け入れる」か「ダイアログを表示する」の設定にしておいてください。

簡易画像掲示板の作成

では簡易画像掲示板を作成していきましょう。まずは、公開するディレクトリ(c:¥xampp¥htdocs)にgz_imgとgz_dataの2つのディレクトリを作成してください。

 

f:id:mkyosuke:20191209180920p:plain

■テーブルの作成

テーブルを作成します。phpMyAdminを使用して、データベース「db」にテーブル「table1」と「table2」を作成します。なお、「table1」のカラム「ban」には必ず「連続番号機能」を設定してください。

次にユーザー情報テーブル「table2」に、ユーザー名とパスワードを登録しますが、これはphpMyAdminから行うことができません。なぜならカラム「pas」は、PHPmd5関数でハッシュ値に変換してからテーブルに格納するからです。そこで、次のようなPHPスクリプトを作成して、実行してください。

g_user_make.php

<?php
$db = new pdo("mysql:host=localhost;dbname=db","root","");
$db->query("INSERT INTO table2(id,pas,nam)VALUES('admin',md5('himitunopass'),'tanaka')");
$db->query("INSERT INTO table2(id,pas,nam)VALUES('user1',md5('inupass'),'dog')");
$db->query("INSERT INTO table2(id,pas,nam)VALUES('user2',md5('nekopass'),'cat')");
$db->query

("INSERT INTO table2(Id,pas,nam)VALUES('user3',md5('usagipass'),'rabbit')");
print"<p>table2にユーザーを作成</p>";
?>

PDODESCデータベースへ接続し、INSERT文でレコードを挿入しているだけですが、カラム「pas」に格納されるデータの指定にmd5関数を使っています。上記はエラー処理などを行っていませんので、必ずphpMyAdminでレコードが挿入されているか確認してください。

レコードの確認

f:id:mkyosuke:20191208174344p:plain

■ログイン処理

ではPHPスクリプトを作成していきましょう。これ以降gz_db_info.php以外のPHPスクリプトは、すべてドキュメントルート(c:¥xampp¥htdocs)に保存します。

最初はログインの仕組みです。次は、ユーザー名とパスワードを送信するログイン画面のHTMLです。それぞれ「user」「pass」の「データを識別する名前」でPOST送信します。

g_login.html

<HTML>
<HEAD>
<META HTTP EQUIV='Content-Type' CONTENT='text/html;charset=UTF-8'>
<TITLE>ログイン画面</TITLE>
<BODY>
<P STYLE='color: red'>ABC写真</P>
ログインしてください<br>
<FORM ACTION="g_logon2.php" METHOD="post">
ユーザ名<INPUT TYPE='text' NAME='user' SIZE ='30'><br>
パスワード<INPUT TYPE="password" NAME ="pass" SIZE ="30">
<INPUT TYPE ="submit" VALUE="送信">
</FORM>
</BODY>
</HTML>

ログイン画面

f:id:mkyosuke:20191209101901p:plain

ここでは、送信するユーザー名とパスワードを入力するテキストボックスの「データを識別する名前」が、それぞれ「user」と「pass」であることを覚えておきます。

ログイン画面「g_login.html」からのユーザー名とパスワードのPOST送信を受けて、ユーザー認証をするのが次の「g_login2.php」です。

 g_login2.php

<?php
session_start();                                                                                                  ①

$u =htmlspecialchars($_POST['user'],ENT_QUOTES);          ②
$p =htmlspecialchars($_POST['pass'],ENT_QUOTES);            ②
require_once("db_init.php");                        ③
?>

<HTML>
<HEAD>
<META HTTP EQIV='Content-Type' CONTENT='text/html;charset=UTF-8'>
<TITLE>ようこそABC写真へ!</TITLE>
</HEAD>
<BODY>

<?php
$ps =$db->query("SELECT pas FROM table2 WHERE id='$u'");      ④
if ($ps->rowCount()>0){                        ⑤
$r =$ps->fetch();                                                                                                 ⑥             
if($r['pas']===md5($p)){                        ⑦
$_SESSION['us']= $u;                          ⑧
?>

<P>ようこそABC写真へ!</P>
<P><A HREF='g.php'>ここをクリックして一覧表示へ</A></P>      ⑨

<?php
}else{
session_destroy();                             ⑩
?>
<P>パスワードが違います。<br>
<A HREF='g_login.html'>ログイン</A></P>                                                      ⑩

<?php
}
}else{
session_destroy();
?>
<P>ユーザーが登録されていません<br>
<A HREF='g_login.html'>ログイン画面へ</A></P>            ⑪
<?php
}
?>
</BODY>
</HTML>

①session_start関数で、セッションを開始
g_login.htmlで送信された「ユーザー名」と「パスワード」の「データを識別す名前

はそれぞれ「user」および「pass」です。

②それぞれを$_POST['user']および$_POST['pass']でPOST送信で受け取ったデータをさらにhtmlspecialcharsでタグを無効化します。

最終的にユーザー名は変数$uに、パスワードは変数$pに代入します。

$u =htmlspecialchars($_POST['user'],ENT_QUOTES);          
$p =htmlspecialchars($_POST['pass'],ENT_QUOTES);          

③データベース初期化ファイル「db_init.php」をrequire_onceで読み込みデータベースを初期化します。

④PDOのqueryメソッドで、SELECT文を実行し、変数$psに代入。

オブジェクト変数$dbでデータベースを読み込む。

$ps =$db->query("SELECT pas FROM table2 WHERE id='$u' ");

カラム「id」が$u(ユーザー名)であることを条件にして、table2の一致するレコードのカラム「pas」に保管されている文字列(パスワード文字をmd5で処理した文字)を検索します。queryメソッドが返すデータは(クエリの結果)は、変数$psに代入しています。

⑤if文で、登録ユーザーかどうかを判断

if ($ps->rowCount()>0){

PDOStatementのrowCountメソッドは結果の行数を返します。これが0より大きければ(id='$u'が存在)登録されたユーザーであると判断、そうでなければ送信されたユーザー名が登録されていないと判断します。もし、この条件にFALSEが返された場合は、session_destory関数でセッションを破棄して、ログインへのリンク(A HREF='g_login.html'>を表示します⑪。

⑥PDOStatementのfetchメソッドによりレコードを取り出し、$rに格納。

⑦teble2の「pas」カラムの値と入力したパスワードの値が正しいかどうかをチェック

if($r['pas']===md5($p)){

===(厳密等価演算子)「右側の値と左側の値は、変数の型(変数の種類)まで含めて同じですか~?」な比較を意味する演算子

md5($p)は送信されてきたユーザー名($p)をmd5で処理したもので、これがユーザー名から検索されたカラム「pas」の値と一致すれば、ユーザー名とパスワードの組み合わせは正しいと判断します。

⑧セッション変数「us」にユーザー名($u)を代入

⑨一覧へのリンク(<A HREF='g.php'>)を表示します。

⑩パスワードが一致しない場合は、セッションを破棄した後、ログインへのリンクを

 表示します。

 実行結果

f:id:mkyosuke:20191211182638p:plain

ユーザーが登録されていない場合

f:id:mkyosuke:20191211182841p:plain

パスワードが違う場合

f:id:mkyosuke:20191211182939p:plain