DB連携ダイアリー
通常のファイルベースの日記帳スクリプトだと、記事を日付順に表示するとかが結構難しいので、ここではより便利になるようにデータベース連携版にする事にしました。データベース連携版だと記事の更新も非常に簡単ですし、ファイルベースのものとは一味違うスクリプトになるはずです。
テーブル構造
今回から文字列データに文字数制限を加えました。
[テーブル作成文]
create table db_diary (code int4, year int2, month int2, day int2,subject varchar(50), msg varchar(500),img_name varchar(30), primary key (code));
インデックス番号
列名
データ型
0 code int4 1 year int2 2 month int2 3 day int2 4 subject varchar(50) 5 msg varchar(500) 6 img_name varchar(30) プログラム内容
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=x-sjis">
<TITLE>KOMOダイアリー(DB連携版)</TITLE>
<STYLE TYPE="text/css">
<!--
:link {
Color : blue ;
Text-Decoration : None
}
:active {
Color : blue ;
Text-Decoration : None
}
:visited {
Color : blue ;
Text-Decoration : None
}
A:hover {
Color : blue ;
Text-Decoration : Underline
}
-->
</STYLE>
</HEAD>
<BODY BGCOLOR="#FFFBF0">
<CENTER>
<P><IMG SRC="title.gif" WIDTH="415" HEIGHT="82" ALIGN="BOTTOM" BORDER="0"></P>
<P><FONT COLOR="#990066"><B>データベース連携の日記帳スクリプトです。記事は日付順(降順)に表示されます。</B></FONT><BR>
パスワードは「777」に設定しています。お試しあれ!(^o^)丿</P>HTMLの最初の部分です。別に難しい所はありませんね。 <?php
//====================初期設定======================
$db_user = "psql"; //データベースのユーザー名(自分の環境に合わせて変更の事)
$db_name = "database"; //データベース名(自分の環境に合わせて変更の事)
$passwd = '777'; //管理者用パスワード
$data_max = 200; //データ最大記録数
$page_view = 5; //1ページの記事表示件数
$this_year = date("Y"); //アクセス時の年
$this_month = date("n"); //アクセス時の月
$this_day = date("d"); //アクセス時の日
$up_dir = '/img/'; //画像保存用ディレクトリ
$w_max = 200; //画像の横幅の最大値(ピクセル)
$h_max = 200; //画像の縦幅の最大値(ピクセル)
$w_limit = 600; //画像の横幅の制限値(ピクセル)
$h_limit = 400; //画像の縦幅の制限値(ピクセル)
//==================================================PHPの開始。
初期設定部分です。データベース接続時のユーザー名とデータベース名は、適当に自分の環境に合わせて変えて下さい。$php_v = PHP_VERSION; //PHPバージョンの取得
if($php_v > "4.1.0"){ //スーパーグローバル変数対応なら
$path = dirname($_SERVER["PATH_TRANSLATED"]).$up_dir;
$PHP_SELF = $_SERVER["PHP_SELF"];
//フォームデータの取得
$action = $_POST['action'];
$code = $_POST['code'];
$year = $_POST['year'];
$month = $_POST['month'];
$day = $_POST['day'];
$subject = $_POST['subject'];
$msg = $_POST['msg'];
$img_name = $_POST['img_name'];
$img_del = $_POST['img_del'];
$button = $_POST['button'];
$password = $_POST['password'];
$e_code = $_POST['e_code'];
$upfile = $_FILES['upfile']['tmp_name'];
$upfile_name = $_FILES['upfile']['name'];
$pline = $_POST['pline'];
}else{
$path = dirname($PATH_TRANSLATED).$up_dir;
}スーパーグローバル変数対策です。最近のサーバではほとんどこの処理が必要です。気をつけましょう(^.^) //===============インライン関数===================
function inline_link($link){
$link = ereg_replace("(https?|ftp|news)(://[[:alnum:]\+\$\;\?\.%,!#~*/:@&=_-]+)","<a href=\"\\1\\2\" target=\"_blank\">\\1\\2</a>",$link);
return $link;
}
//================================================コメント内にリンク記述部分があれば、自動でリンク表示を施します。 if(!$d_base = pg_connect("user=psql dbname=database")){ //データベースに接続
$err_msg = "データベースへの接続に失敗しました。";
}データベースに接続します。接続できなかったときのエラー処理を施しています。 if($action == "regist"){
//処理の分岐
if($button == "修正/更新"){
//インラインリンクを実現(URLのみ)
$msg = inline_link($msg);
if(strlen($msg) < 500){
//画像を削除
if($img_del){
unlink(".".$up_dir.$img_name);
}
if($upfile){
$source = $upfile;
$source_name = $upfile_name;
$source_name = ereg_replace("^(.:.*\\\\)?(.*)", "\\2", $source_name);
if(($source != "none")&&($source != "")){
$dest = $path.$source_name;
$imagesize = getimagesize($source);
if(($imagesize[0] > $w_limit) || ($imagesize[1] > $h_limit)){ //大きな画像のアップを制限
$err_msg = "画像のサイズが大き過ぎて登録できませんでした。";
}else{
if(copy($source,$dest)){
$imagesize = getimagesize($dest);
switch($imagesize[2]){
case 0:
unlink($dest);
break;
case 1:
$out = $code.".gif";
rename($dest,$path.$out);
break;
case 2:
$out = $code.".jpg";
rename($dest,$path.$out);
break;
case 3:
$out = $code.".png";
rename($dest,$path.$out);
break;
}
}
$img_name = $out;
}
}
}
//アップデート
pg_exec($d_base, "update db_diary set code = " . $code . ",year = " . $year . ",month = " . $month . ",day = " . $day . ",subject = '" . $subject . "',msg = '" . $msg . "',img_name = '" . $img_name . "' where code = " . $code);
//再読み込み
echo "<META HTTP-EQUIV=refresh content=0;URL=$PHP_SELF>";
exit;
}else{
$err_msg = "コメントの文字数が多すぎます。";
}
}書き込み処理部分です。
変数$buttonの値によって処理を分けています。ここは修正更新処理部分です。
メッセージの文字数制限を設けていますので、注意が必要です。
画像削除の為の変数$img_delがセットされていれば、unlink関数を使って画像を削除します。
★int unlink( string filename )関数…引数filename で指定されたファイルを削除します。成功すると0を返し、エラーの場合はfalseを返します。
次は、画像の修正アップロード処理部分です。アップロードしようとしている画像のサイズに制限を設けています。
データベースのアップデートには「update」SQL文を使います。画像表示を更新する為、リフレッシュしている点に注意して下さい。if($button == "削除"){
if($code){
//画像の削除処理
$result = pg_exec($d_base, "select * from db_diary where code = " . $code);
$arr = pg_fetch_row($result, 0); //検索結果の一行分を配列に格納
$img_name = $arr[6];
unlink(".".$up_dir.$img_name);
//該当データを削除
pg_exec($d_base, "delete from db_diary where code = " . $code);
}
}削除処理部分です。
まず、送られてきたコード$codeの値から、格納されている画像ファイル名を取得し、unlink()関数を使って画像を削除します。
次に「delete」SQL文を使って、該当データを削除しています。if($button == "送信/更新"){
if($msg){
$code = time(); //アクセス時の秒数
//インラインリンクを実現(URLのみ)
$msg = inline_link($msg);
if(strlen($msg) < 500){
if($upfile){
$source = $upfile;
$source_name = $upfile_name;
$source_name = ereg_replace("^(.:.*\\\\)?(.*)", "\\2", $source_name);
if(($source != "none")&&($source != "")){
$dest = $path.$source_name;
$imagesize = getimagesize($source);
if(($imagesize[0] > $w_limit) || ($imagesize[1] > $h_limit)){ //大きな画像のアップを制限
$err_msg = "画像のサイズが大き過ぎて登録できませんでした。";
}else{
if(copy($source,$dest)){
$imagesize = getimagesize($dest);
switch($imagesize[2]){
case 0:
unlink($dest);
break;
case 1:
$out = $code.".gif";
rename($dest,$path.$out);
break;
case 2:
$out = $code.".jpg";
rename($dest,$path.$out);
break;
case 3:
$out = $code.".png";
rename($dest,$path.$out);
break;
}
}
$img_name = $out;
}
}
}else{
$img_name = '';
}
pg_exec($d_base, "insert into db_diary values ($code,$year,$month,$day,'$subject','$msg','$img_name')");
//データ最大記録数を調整
if($result = pg_exec($d_base, "select * from db_diary order by code DESC")){
$row = pg_numrows($result); //検索結果の行数を取得
if($row > ($data_max * 1.2)){
$arr = pg_fetch_row($result, $data_max);
$max_arr = $arr[0];
pg_exec($d_base, "delete from db_diary where code <= $max_arr");
}
}
}else{
$err_msg = "コメントの文字数が多すぎます。";
}
}else{
$err_msg = "コメントが書き込まれていません。";
}
}新規登録処理部分です。
time()関数を使って、アクセス時の秒数を取得し、それを変数$codeの値に使っています。
メッセージの文字数制限を設けていますので、注意が必要です。
後はいつもの画像のアップロード処理です。
最初の書き込み処理ですから、データベースへの登録は「insert」SQL文を使います。
データベースへの新規登録処理が終わった後、記事の最大記録数の調整を行ないます。
まずデータをコードの値を元に降順に取得します。次に取得したデータの行数(記事数)を取得します。これを初期設定の「データ最大記録数」と比較して、1.2倍を超えていれば削除処理に移ります。1.2倍に設定したのは、記事数が「データ最大記録数」を超えた場合に、いちいち削除処理を行っていたのでは、パフォーマンスが下がるからです。
削除処理は以下のような順序で行なわれています。まず、pg_fetch_row()関数を使って、初期設定の「データ最大記録数」部分に当たるデータ1行分を取得します。次にそのコードの値を取得し、データベースからコードの値がその取得したコードの値以下のものを削除します。
★array pg_fetch_row( int result, int row )関数…数字をインデックスとする配列として行を取得します。行がもうない場合にfalseを返します。
コードの値は、古い記事ほど値が小さいことに注意しましょう。}elseif(($action == "edit") && ($password == $passwd)){
$kanri_flag = 1; //管理マドの表示制御用フラグ
echo "<form action=$PHP_SELF method=POST ENCTYPE=multipart/form-data>\n";
echo "<input type=hidden name=action value=regist>\n";
if($e_code) {
if($result = pg_exec($d_base, "select * from db_diary where code = " . $e_code)){
$arr = pg_fetch_row($result, 0); //検索結果の一行分の各値を配列に格納
$e_code = $arr[0];
$e_year = $arr[1];
$e_month = $arr[2];
$e_day = $arr[3];
$e_subject = $arr[4];
$e_msg = $arr[5];
$img_name = $arr[6];
}
echo "<input type=hidden name=code value=\"$e_code\">\n";
echo "<input type=hidden name=img_name value=\"$img_name\">\n";
echo "<table border=0>\n";
echo "<tr><td align=right><B>日付:</B></td><td><SELECT NAME=year>";
for($i=$this_year-1; $i<$this_year+5; $i++){
echo "<OPTION" . (($e_year == $i) ? ' SELECTED' : '') . ">$i</OPTION>";
}
echo "</SELECT>年<SELECT NAME=month>";
for($i=1; $i<13; $i++){
echo "<OPTION" . (($e_month == $i) ? ' SELECTED' : '') . ">$i</OPTION>";
}
echo "</SELECT>月<SELECT NAME=day>";
for($i=1; $i<32; $i++){
echo "<OPTION" . (($e_day == $i) ? ' SELECTED' : '') . ">$i</OPTION>";
}
echo "</SELECT>日</td></tr>\n";
echo "<tr><td align=right><B>題名:</B></td><td><input type=text size=35 name=subject value=\"$e_subject\"></td></tr>\n";
echo "<tr><td align=right><B>コメント:</B></td><td><textarea name=msg rows=6 cols=50>$e_msg</textarea></td></tr>\n";
echo "<tr><td align=right><B>添付画像:</B></td><td>上書<INPUT TYPE=file NAME=upfile SIZE=35> 削除<INPUT TYPE=CHECKBOX NAME=img_del VALUE=1></td></tr>\n";
echo "</table>\n";
echo "<input type=submit name=button value=修正/更新> <input type=submit name=button value=削除>\n";管理編集処理部分です。
管理マドから送られたパスワードの値が合っていれば、管理編集処理に移ります。
変数$e_codeの値の有無によって、「新規登録モード」か「修正モード」かの判断を行なっています。
ここは、変数$e_codeの値がある場合ですから、「修正モード」になります。
まずデータベースから、該当のコードに当たる記事の値をpg_fetch_row()関数を使ってそれぞれ取得します。取得したそれぞれの値は、投稿フォームのそれぞれの値に読み込んでいます。}else{
echo "<table border=0>\n";
echo "<tr><td align=right><B>日付:</B></td><td><SELECT NAME=year>";
for($i=$this_year-1; $i<$this_year+5; $i++){
echo "<OPTION" . (($this_year == $i) ? ' SELECTED' : '') . ">$i</OPTION>";
}
echo "</SELECT>年<SELECT NAME=month>";
for($i=1; $i<13; $i++){
echo "<OPTION" . (($this_month == $i) ? ' SELECTED' : '') . ">$i</OPTION>";
}
echo "</SELECT>月<SELECT NAME=day>";
for($i=1; $i<32; $i++){
echo "<OPTION" . (($this_day == $i) ? ' SELECTED' : '') . ">$i</OPTION>";
}
echo "</SELECT>日</td></tr>\n";
echo "<tr><td align=right><B>題名:</B></td><td><input type=text size=35 name=subject></td></tr>\n";
echo "<tr><td align=right><B>コメント:</B></td><td><textarea name=msg rows=6 cols=50></textarea></td></tr>\n";
echo "<tr><td align=right><B>添付画像:</B></td><td><INPUT TYPE=file NAME=upfile SIZE=35></td></tr>\n";
echo "</table>\n";
echo "<input type=submit name=button value=送信/更新> <input type=reset value=リセット>\n";
}
echo "</form>\n";
}管理編集処理部分です。
ここは変数$e_codeの値がありませんので、新規登録処理になります。投稿フォームを表示して、新規に投稿データを書き込み、アップロードします。//エラー処理
if($err_msg){
echo "<FONT COLOR='red'>" . $err_msg . "</FONT>";
echo "<BR><BR><A HREF=$PHP_SELF onMouseOver=this.style.color='red' onMouseOut=this.style.color='blue'><やり直す></A>\n";
exit;
}ここは、今までの処理中でエラーが発生した場合の、エラー告知(表示)処理部分です。
「exit;」でこれ以降の処理を抜けます。echo "<form action=$PHP_SELF method=POST>\n";
echo "<input type=hidden name=mode value=sort>\n";
echo "<input type=hidden name=action value=\"$action\">\n";
echo "<input type=hidden name=password value=\"$password\">\n";
echo "<input type=hidden name=pline value=\"$pline\">\n";
echo "<B>文字列検索:</B><FONT SIZE=2>題名又はコメントに文字列</FONT><input type=text size=20 name=search_str><FONT SIZE=2>を含む</FONT> <input type=submit name=submit value=送信> <input type=reset value=リセット></FORM>\n";記事中に文字列検索をかける為のフォームを表示します。 if($mode == 'sort'){
if($search_str){
$SQLstr = "select * from db_diary where subject like '%" . $search_str . "%' or msg like '%" . $search_str . "%' order by year DESC, month DESC, day DESC";
}else{
$SQLstr = "select * from db_diary order by year DESC, month DESC, day DESC";
}
}else{
$SQLstr = "select * from db_diary order by year DESC, month DESC, day DESC";
}文字列検索がかけられた場合と通常の場合とで、記事表示の為のデータ取得用SQL文を書き分けます。 if($result = pg_exec($d_base, $SQLstr)){
$row = pg_numrows($result); //検索結果の行数を取得
if($row > 0){
if($pline == ""){
$p_line = 0;
}else{
$p_line = $pline;
}
$end_data = $row - 1;
$page_end = $p_line + ($page_view - 1);
if($page_end >= $end_data)
$page_end = $end_data;
for($i=$p_line; $i<=$page_end; $i++){
$arr = pg_fetch_row($result, $i); //検索結果の一行分を配列に格納
//曜日を生成
$date_str = $arr[1] . "/" . $arr[2] . "/" . $arr[3];
$date_timestamp = strtotime($date_str);
$week_day = strftime("%a", $date_timestamp);
if($week_day == 'Sun'){
$font1 = "<FONT COLOR='red'>";
$font2 = "</FONT>";
}elseif($week_day == 'Sat'){
$font1 = "<FONT COLOR='blue'>";
$font2 = "</FONT>";
}else{
$font1 = "";
$font2 = "";
}
echo "<form action=$PHP_SELF method=POST>\n";
echo "<input type=hidden name=action value=edit>\n";
echo "<input type=hidden name=e_code value=\"$arr[0]\">\n";
echo "<input type=hidden name=pline value=$pline>\n";
echo "<table border=1 width=90% bordercolor=#555555>\n";
echo "<tr><td>■<b>" . $arr[1] . "/" . $arr[2] . "/" . $arr[3] . "(" . $font1 . $week_day . $font2 . ")</B>\n";
echo " <font color='green' size=4><b>" . $arr[4] . "</b></font>\n";
if (($action == "edit") && ($password == $passwd)) {
echo "<input type=hidden name=password value=$passwd> <input type=submit value=訂正>\n";
}
echo "</td></tr><tr><td><blockquote>\n";
if($arr[6]){
$img_name = $arr[6];
if(file_exists("$path$img_name")){
$size = getimagesize("$path$img_name");
$img_w=$size[0];
$img_h=$size[1];
if($img_w > $w_max || $img_h > $h_max){
$w_ritu = $w_max / $img_w;
$h_ritu = $h_max / $img_h;
($w_ritu < $h_ritu) ? $key = $w_ritu : $key = $h_ritu;
$width = (int) $img_w * $key;
$height = (int) $img_h * $key;
echo "<A HREF=.$up_dir$img_name TARGET=_blank><img src=.$up_dir$img_name WIDTH=" . $width . " HEIGHT=" . $height . " ALIGN=LEFT></A>";
}else{
echo "<img src=.$up_dir$img_name ALIGN=LEFT>";
}
}
}
$msg = nl2br($arr[5]);
echo $msg . "</blockquote></td></tr></table></form>\n";
}
}else{
echo "<FONT COLOR='red'>登録されている記事がありません。</FONT>";
}
}
?>記事表示部分です。
データベースから記事データを取得し、pg_numrows()関数を使って記事の行数(記事の件数)を取得します。
★int pg_numrows( int result_id )関数…引数result_id で指定されたPostgreSQLの結果IDにおける行数を返します。引数は、pg_Exec()で返された有効な結果IDです。この関数は、エラーの際に-1を返します。
pg_fetch_row()関数を使って、記事の各行のデータを取得します。各行のデータを配列変数$arrに格納し、それぞれの場所に該当の値を表示します。
画像の表示部分の処理内容は、通常の画像掲示板と同様です。<P>
<TABLE BORDER="0" WIDTH="600">
<TR>
<TD WIDTH="50%">HTML部分 <?php
if($page_end >= $page_view){
$page_count = floor($page_end / $page_view);
$prev_line = ($page_count - 1) * $page_view;
echo "<form method=Post action=$PHP_SELF>\n";
if (($action == 'edit') && ($password == $passwd)){
echo "<input type=hidden name=action value=edit>\n";
echo "<input type=hidden name=password value=$passwd>\n";
}
echo "<input type=hidden name=pline value=$prev_line>\n";
echo "<input type=hidden name=sort_flag value=$sort_flag>\n";
echo "<input type=submit value=前のページ>\n";
echo "</form>\n";
}else{
echo " \n";
}
?>「前のページ」への移動用ボタンを表示します。処理内容は通常の掲示板スクリプトと同じです。 </TD>
<TD WIDTH="50%"><P ALIGN="RIGHT">HTML部分 <?php
$next_line = $page_end + 1;
if($page_end != $end_data){
echo "<form method=Post action=$PHP_SELF>\n";
if (($action == 'edit') && ($password == $passwd)){
echo "<input type=hidden name=action value=edit>\n";
echo "<input type=hidden name=password value=$passwd>\n";
}
echo "<input type=hidden name=pline value=$next_line>\n";
echo "<input type=submit value=次のページ>\n";
echo "</form>\n";
}else{
echo " \n";
}
?>「次のページ」への移動用ボタンを表示します。処理内容は通常の掲示板スクリプトと同じです。 </TD>
</TR>
</TABLE>HTML部分 <?php
if($kanri_flag < 1){
echo "<div align=left>\n";
echo "<form action=$PHP_SELF method=POST>\n";
echo "<input type=hidden name=action value=edit>\n";
echo "<input type=password size=10 name=password>\n";
echo "<input type=hidden name=pline value=$pline>\n";
echo " <input type=submit value=管理><br>\n";
echo "</form></div>\n";
}
?>管理用ページに移るためのフォームを表示します。変数$kanri_flagの値によって、表示の有無をコントロールします。 </BODY>
</HTML>HTML部分の終わり <サンプルだよ!>
*上の内容をこのまま複写しても動きません。何故なら、表示を見やすくする為コード中に全角スペースが入っているからです。実際にお使いになる時は、この点を修正してからサーバにアップして下さい。
DB連携掲示板スペシャル 前へ
次へ DB連携Accessアナライザー