掲示板の作り方#6 スレッド登録の準備をする
こんにちは。Suipediaです(∩´∀`)∩。
前回はスレッド作成の入力フォームを作りました。
こんな画面ができたんでしたね。顔アイコンの部分のみまだですが、#9で実装するのでご心配なく。
今回は入力されたデータの登録を行いますので、本格的なプログラミングになります。なぜならデータベースとの連携という新しい処理が入ってきますからね( *´艸`)
では参りましょう。
今回のゴール
今の時点ではなんのことかわからないと思いますが・・・
画面的にはこのようなデータを入れる表ができるようになるところを今回のゴールとして進めていきましょう。
あとはサーバにデータを渡す準備をします。
掲示板システムのデータのもちかた
データを登録する前にまずこのシステムではデータをどのように保持するのか、という点について理解せねばなりません。
これをご覧ください
掲示板を実現するにあたって必要なデータは大きく2つに分かれます。
ひとつはスレッド、もう一つは各スレッドが保持するメッセージです。上図のようにスレッド毎に子どもとなるメッセージたちがぶら下がります。
スレッドというのは掲示板の中で展開されるやりとり群の単位です。
メッセージはやりとりされるメッセージの1つ1つです。
最初に完成形のデータの持ち方をご覧いただきましょう。こちらです。
小さくて見えにくい場合は画像をクリックすると拡大表示できます。
こちらはスレッドを管理するために必要な情報の一覧です。この、データを管理する表のことをテーブルといいます。上図の場合スレッドテーブルと呼びます。
まだ各項目についての説明はしないので「へ~(・∀・)」くらいに留めておいてください。
次にメッセージを見ていただきましょう。
こちらもエクセルみたいな感じでデータを管理しています。データはサンプルサイトのものです。
ここで注目してほしいのはただ1点だけ。メッセージテーブルの項目にはひとつだけ先ほどのスレッドテーブルにもあった項目が存在します。
それがスレッドIDです。
メッセージテーブルから見て親となるスレッドテーブルのスレッドIDをもっていることで、どのスレッドの子どもか?ということを判別できるんです。
こんなことになったりしたらシステムとして機能しませんからね。親テーブルのID項目を子テーブルにももつことで整理されたデータ保持ができます。
この「親テーブル」とか「子テーブル」、「データの親子関係」という言い回しはこの業界では割とよくします。今の説明のために便宜的に使っているのではないので頭に留めておいてください。
ここの説明は実際に作りこんでいく中でより明確に理解できてくると思いますので、今はよくわからなくてもご安心くださいね(∩´∀`)∩。
テーブルをつくろう
では、次はテーブルをつくりましょう。スレッドテーブルからいきます。
テーブルを作るにはまずデータを管理するための画面を開く必要があります。
コントロールパネルから赤枠のStartボタンを押下してください。これはデータを管理するMySQLというソフトフェアを起動しています。
クリックしていただいたら次にその隣のAdminボタンを押下しましょう。
クリックしていただくと、ブラウザに新しいタブが開いたでしょうか。
こういうのが開いていればOKです。
次に左サイドに並んでいるテキストの中から「test」をクリックしてください。(下図の赤枠)
こんな画面になればOKです。まだなにもしていないので、
「~テーブルがありません。」という表示になっています。
ではテーブルを追加します。テーブルの追加には2つの方法があるのですが、手間のかからない方で行います。
上部のSQLタブをクリックしてください。
すると・・・
このような画面になりました。
「データベース test 上でクエリを実行する」という表示がありますね。
ここでまたしても新しい知識を仕入れましょう。データベースを操作する言語のことをSQL(えすきゅーえる)といい、Query(クエリ)とも呼びます。
Queryは問い合わせという意味の英語なので、データベースに問い合わせする、という意味です。「クエリを実行する」を意訳するとデータベースに対してなにか操作を行う、ということになります。
クエリの入力枠に以下のクエリを貼ってください。(ここは打たずにコピー&ペーストでよいです)
CREATE TABLE IF NOT EXISTS `bbs_thread` (
`threadId` int(10) NOT NULL AUTO_INCREMENT COMMENT 'スレッドID',
`title` varchar(200) NOT NULL COMMENT 'スレッドタイトル',
`pass` varchar(1000) NOT NULL COMMENT 'パスワード',
`closeflg` varchar(1) NOT NULL COMMENT '閉じるフラグ',
`disabledflg` varchar(1) NOT NULL COMMENT '無効フラグ',
`createdy` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '登録日',
`updatedy` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新日',
PRIMARY KEY (`threadId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='掲示板のスレッド管理' AUTO_INCREMENT=1 ;
このようになっていればOKです。右下にある実行ボタンを押下しましょう。
このような表示になればOKです。左側にテーブルが追加されていますね。
次にメッセージテーブルも追加します。今やったスレッドテーブルと同じ要領で、以下のクエリを実行してください。
CREATE TABLE IF NOT EXISTS `bbs_message` (
`serialId` int(10) NOT NULL AUTO_INCREMENT COMMENT 'シリアル番号',
`threadId` int(10) NOT NULL COMMENT 'スレッドID',
`id` int(4) NOT NULL COMMENT 'スレ内投稿ID',
`userType` varchar(1) DEFAULT NULL COMMENT '1:主、2:レス',
`iconId` varchar(30) NOT NULL COMMENT '顔アイコン',
`name` varchar(30) NOT NULL COMMENT '名前',
`message` varchar(5000) NOT NULL COMMENT '本文',
`pass` varchar(1000) NOT NULL COMMENT 'パスワード',
`disabledflg` varchar(1) NOT NULL COMMENT '無効フラグ',
`createdy` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '登録日',
`updatedy` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新日',
PRIMARY KEY (`serialId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='掲示板のメッセージ管理' AUTO_INCREMENT=1 ;
このようになればOKです。
今回使ったクエリはデータベースにテーブルを作成するSQLなのですが、たまにしか使わない上に、今はこの説明は必要ないので割愛します。
必要なシーンが訪れたら・・・#8で改めて説明しますね。
スレッドテーブルの項目について
今おつくりいただいた2つのテーブルがもつ項目についても簡単に説明しておきましょう。まずはスレッドテーブルから。
さらさら~っと眺めていただく程度で大丈夫です。
■スレッドID(threadId)
スレッドの管理番号です。データを特定する目的があるので重複してはいけません。
■スレッドタイトル(title)
スレッドのタイトルです。スレッドを立てたユーザが入力した内容を格納します。
■パスワード(pass)
登録ユーザが再度メッセージを登録する際にスレッド主かどうかを判定するために保持します。またどこかで説明します。
■閉じるフラグ(closeflg)
スレッド主がこれ以上メッセージを受け付けなくていいと判断した場合に画面上でレスポンスフォームを表示させなくするためのフラグです。
■無効フラグ(disabledflg)
スレッドは存在するけど、何らかの事情で画面に表示させたくないとき等に使います。またどこかで説明します。
■登録日(createdy)
スレッドの登録日です。ただの管理項目です。
■更新日(updatedy)
スレッドの更新日です。こちらもただの管理項目ですが、スレッドの並びは更新順のため、そこで利用されている点は登録日と異なります。
メッセージテーブルの項目について
次にメッセージテーブルの項目説明です。
■シリアル番号(serialId)
ただの管理番号です。すべてのメッセージで一意(重複しない)になります。
■スレッドID(threadId)
スレッドテーブルにもあるスレッドIDです。このIDでどのスレッドの中に表示されるメッセージかを判別します。
■スレッド内投稿ID(id)
スレッド内での管理番号です。
■ユーザタイプ(userType)
ユーザはスレッド主とそれ以外、という2つのタイプに分かれます。それを管理する項目です。
■アイコンID(iconId)
今回おつくりいただく掲示板はメッセージの投稿時にキャラクターアイコンを選択できます。それを管理するのがこの項目です。後続記事(#9)で出てくるアイコンテーブルを参照します。
■名前(name)
投稿者の名前です。
■メッセージ(message)
投稿されたメッセージを管理します。
■パスワード(pass)
あれ?(*´Д`)このテーブルにパスワードはいらないはず・・・。すみません。パスワードを使うところに行くまでに精査しておきます。
■無効フラグ(disabledflg)
誹謗中傷等、表示したくないメッセージがあったときはこのフラグを立てて、画面に表示しないようにします。
■登録日(createdy)
管理項目です。データができたタイミングの日付・時間を保持します。
■更新日(updatedy)
登録日同様、ただの管理項目です。メッセージは更新されることがないため、登録日と同じ情報が入ります。
では、次行きましょう。パスワードの箇所は不要なことがハッキリしたらまた別途,列を削除しますね。
クライアントサイドとサーバサイドについて
ここまでの作業で、画面で入力されたデータを永続的に保持する入れ物(テーブル)ができました。
となると、いよいよここからデータの登録を実装していくのですが、その前に「どういう仕組みでデータを登録できるの?」というところをスッキリしておきたいですよね。
ご説明します。
まず、webサイトの表示や処理にはクライアントサイド、サーバサイドという2つの場所で処理が行われます。「サイド」は「側」と直訳してください。
クライアントというのはwebサイトにアクセスしてきたユーザのことです。今このnoteを見ているあなたもまたクライアントです。クライアント側の処理というのは主にブラウザで行われる処理だと解釈してください。
サーバから受け取ったHTMLファイルを表示したり、JavaScriptというプログラムを実行したりするのがクライアント側の処理です。
これに対して世界のどこかにあるサーバがサーバサイドと言われるものの正体です。すごくセキュリティの厳しい場所で管理されています。
「サーバ」で画像検索すると実際のブツを見ることができます。
で、クライアントとサーバでやり取りをしながら表示や処理をするんですね。
こんな感じに。めっちゃ簡素な図(;´Д`)
で、今回の説明に戻ると、クライアントからサーバに向けて
「このデータたちをデータベースに登録してちょうだい!」
というお願いをします。するとサーバ側は
「がってん承知でぃ!!」
と言ってデータベースに登録してくれるんです。
・・・という処理を今から実装します。ちなみに、今あなたが作ろうしている掲示板システムのサーバはどこにあるの?というとそれが#2で入れていただきましたxamppです。
つまり、この開発環境ではサーバは世界のどこかではなく、あなたのパソコンの中にあります。便利なツールがあったもんですねぇ( *´艸`)
データをサーバに投げる処理を書こう
ではでは、ここまでの説明を踏まえて、クライアントサイドからサーバサイドへデータを投げる処理を実装していきます。
(この界隈ではよくリクエストやデータを「投げる」と言います。「渡す」と同じ意味です。)
方法はいくつかありますが、今回はAjax(えいじゃっくす)を使います。あとで説明します。
では、newフォルダ内のc.phpの5行目のコメントアウトを解除します。
ここの書き方は相対パスですね。newフォルダ内にscript.phpを用意する必要があります。
以下のファイルをダウンロードし、newフォルダに置いてください。
今回もソースが長めなので、打っていただくことはせずファイルを渡しました。
データをサーバに投げるにはJQuery(じぇいくえりぃ)を使います。
ここでまた「JQueryとは~」と言い出すと、長くなるうえに混乱させるだけだと思うので、ブラウザ(クライアント)側で動くプログラムだと思ってください。ちなみにPHPはサーバ側で動くプログラムです。
渡したファイルの中身を要所のみ解説します。
このファイルの中でやる処理内容は
・サーバに投げるデータの準備
・処理をリクエストする(データを投げる)場所の指定
・サーバから返ってきたときの処理
です。
サーバに投げるデータの準備
では、今渡したscript.phpの中の9~16行目あたりをみてください。
/* POSTメソッドで送るデータを定義します var data = {パラメータ名 : 値}; */
var bbsData = {
title : $('#title').val(),
name : $('#name').val(),
icon : $('#selectIconValue').val(),
message : $('#message').val(),
pass : $('#pass').val()
};
ここでサーバにわたすデータを用意しています。
なんとな~く理解できると思うんですが、タイトルを例に見てみましょう。
title : $('#title').val(),
こんな書き方をしていますね。これは
key : value
(キー:バリュー)
という書き方をしており、「鍵:値」ということです。
まず、コロンの左側にある「title」はキーなので、これに紐づくデータをコロンの右側である値を書く場所に指定します。
値のところにある
$('#title').val(),
というステートメント(処理命令)は今いるページのHTMLの中からidに「title」が指定された要素のvalue属性を取得する、という働きをします。
ということは、フォームのどこかにidにtitleが指定された要素があるはずです。なんとなく察しはついていることでしょう。
前回お渡ししたform.phpを見てみてください。
22行目のinputタグ(いんぷっとたぐ)がユーザが入力する枠なのですが、ここに「id="title"」という記載がありますね。ここの記載とjQuery側の処理がリンクすることでユーザの入力内容を
title : $('#title').val(),
この左側の「title」に持たせることができます。
これに併せて覚えておいてほしいことがもうひとつあります。
例えばですが、同じページ内に「id="title"」という属性を付けているHTMLタグが2つあったとしたらjQueryはどちらのvalueを取得するでしょうか?
答えはエラーになって取得できない、です(たしか)。
ページ内にある無数のHTMLタグには同じidを指定してはいけない、という決まりがあります。必ず、一意(いちい)になるようにしましょう。「一意」とは重複しないという意味です。
このidは一意にするんだぞ、という話は#9でも出てくるので今忘れても大丈夫です( *´艸`)web開発にあたって基本でありまた重要な点でもあります。
で、話を戻しまして・・・
title : $('#title').val(),
name : $('#name').val(),
icon : $('#selectIconValue').val(),
message : $('#message').val(),
pass : $('#pass').val()
同じ要領でname、icon、message、passの各値をサーバに送る準備ができます。
処理をリクエストする(データを投げる)場所の指定
script.phpの18~28行目を見てください。
/**
* Ajax通信メソッド
* @param type : HTTP通信の種類
* @param url : リクエスト送信先のURL
* @param data : サーバに送信する値
*/
$.ajax({
type: "POST",
url: "/src/server/threadInsert.php",
data: bbsData,
async:false,
ここではAjax通信でサーバに投げるための準備をしています。
まずは先ほど後回しにしたAjax通信(えいじゃっくすつうしん)についてご説明しましょう。
※ここからの説明は掲示板の開発に必要、というよりは学習的な意味合いが強いので、読み飛ばしていただいても大丈夫です汗 難しいと思います※
Ajax通信は別名「非同期通信」とも言います。・・・意味不明ですよね。
まず、クライアントとサーバ間の通信について簡単におさらいします。
あなたがブラウザを操作している中でサーバにリクエスト(なにかを要求)するのは主にどんなときでしょう。・・・はい、ページにアクセスしたときが最も多いです。
任意のURLにアクセスしたとき、そのURL(世界のどこかにあるサーバのフォルダ)にHTMLファイルがあれば返してくれます。返すことをレスポンスと言います。
この要求(リクエスト)と返答(レスポンス)が処理の1セットです。で、例えばF5キーで画面更新なんかするとリクエストを飛ばし、サーバからの返答があるので、それに従ってブラウザは画面を再描画します。
ネット環境が悪かったり、表示したい画像が大容量だったりした場合、画面が真っ白になってなかなか描画されない、というのを経験したことはないでしょうか。
これは、ブラウザがサーバからのレスポンスを待っているからです。この待っている、という部分が同期通信の本髄です。
非同期通信の場合はブラウザ側(クライアントサイド)はサーバからの応答を待たずに次の処理に進むことができます。
で、ここの説明にあたって最も私を苦しめたのが、次の一文なんです。
async:false,
これね(゚Д゚;)ここまで非同期通信の説明を熱心にしてきたんですが、この1文は「非同期通信ではなく同期通信にする」という意味なんです(;´Д`)
つまり、サーバからの応答を待つということです。
このスクリプトでスレッドを登録した後はスレッドページに遷移させる処理の流れなのですが、なぜサーバからの応答を待つようにしているかというとユーザに対して登録処理成功のメッセージを表示したいからなんです。
サーバ側で処理が完了しないとユーザにメッセージを出すことはできませんよね。完了していないのにメッセージを出すと嘘をついていることになりますから。
ですので、非同期非同期と言ってきましたがここでやっているのは同期通信処理です。
じゃあなぜAjax通信を使っているんだ、という話になるのですが、これは画面更新(再読み込み)が伴わないため、と解釈してください。
画面が再読み込みされるとユーザに入力いただいた内容はクリアされてしまいます。ですが、サーバにリクエスト(データ)を投げたからと言って必ずデータが登録されるとは限りません。
入力内容に不備があったときなんかがこれにあたりますね。ですので、画面を再描画することなくクライアントとサーバでやり取りするためにAjax通信を使っている、とご理解ください。
■■■読み飛ばしていただいていいエリアはここまで■■■
では話を戻します。
type: "POST",
url: "/src/server/threadInsert.php",
data: bbsData,
async:false,
この4行で、
・どんな通信手段をとるのか
・どこに処理を投げるのか
・どんなデータを投げるのか
・同期処理?非同期処理?
を指定しています。
■type: "POST",
通信の種類にはGET(ゲット)とPOST(ポスト)があるのですが、ここではPOSTを使います。説明は割愛しますので、興味ある方は別途調べてみてください。
■url: "/src/server/threadInsert.php",
リクエストを投げるURLを指定しています。このthreadInsert.phpというファイルは後で用意することになります。そのファイルの中でデータベースへの登録処理を実施します。
■data: bbsDta,
投げるデータを指定しています。先ほどデータを用意する項で
var bbsData = {
title : $('#title').val(),
name : $('#name').val(),
icon : $('#selectIconValue').val(),
message : $('#message').val(),
pass : $('#pass').val()
};
このように書いていました。「var bbsData = {」と書いてますよね。このbbsDataをdataに指定しているというわけです。
■async:false,
Ajaxのデフォルト(初期状態)の動きは非同期通信なので、falseを指定することで同期通信にしています。ユーザに処理完了のメッセージを表示するためにサーバの応答を待ちたいという事情があり、同期通信にしています。
サーバから返ってきたときの処理
実際の処理の流れは先ほど案内したURLのファイルへ遷移します。
で、ここでは処理をしてレスポンスが返ってきた部分の説明をします。
/**
* Ajax通信が成功した場合に呼び出されるメソッド
*/
success: function(data, dataType){
if(data =='noTitle'){
alert('タイトルが入力されていません。');
}else if(data =='noName'){
alert('名前が入力されていません。');
}else if(data =='noIcon'){
alert('顔アイコンが選択されていません。');
}else if(data =='noMsg'){
alert('メッセージが入力されていません。');
}else if(data =='noPass'){
alert('パスが入力されていません。');
}else{
alert('送信しました。ありがとうございます。');
location.href="/thread/" + data + "/";
}
},
はい、長いソースが現れました。script.phpの29~47行目です。
サーバからも値をこちらに返すことができるのですが、その値はdataという変数に入っています。(JavaScriptの場合、PHPと違い変数の頭に「$」はつけません)
success: function(data, dataType){ ←このdataね
で、サーバの中ではエラーチェックが働くのでその受け皿をif文で用意しています。
前回(#5)でif文の最も簡単な形はPHPプログラムでお伝えしました。ここではその発展形であるelse if(えるす いふ)とelse(えるす)を使っています。
else ifは私の中では「~じゃなかったら~かどうか」と訳しています。
if(data =='noTitle'){
alert('タイトルが入力されていません。');
}else if(data =='noName'){
alert('名前が入力されていません。');
}else if(data =='noIcon'){
alert('顔アイコンが選択されていません。');
}else if(data =='noMsg'){
alert('メッセージが入力されていません。');
}else if(data =='noPass'){
alert('パスが入力されていません。');
}else{
alert('送信しました。ありがとうございます。');
location.href="/thread/" + data + "/";
}
最初は通常のif文で検証します。dataが'noTitle'かどうか、ですね。
その後はelse ifが続くのですが、
dataが'noTitle'じゃなかったら、'noName'かどうか、
dataが'noName'じゃなかったら、'noIcon'かどうか、
dataが'noIcon'じゃなかったら、'noMsg'かどうか、
dataが'noMsg'じゃなかったら、'noPass'かどうか、
・・・と順番に見ています。
else if文の特徴はどこか一つの式にしか入らない点です。つまり、else ifの処理の並びに該当する(trueを返す)評価式が複数あったとしても一番最初の式に入ると、あとの式はスルーされます。
そしてこの手の処理を書く場合、いずれにも該当しなかったときの受け皿も用意したいケースが多いです。それを担ってくれるのがelse文です。
}else{
alert('送信しました。ありがとうございます。');
location.href="/thread/" + data + "/";
}
ここまでのelse ifのいずれにも入らなかった場合、elseで吸収します。
今回の場合、それは登録処理の成功を意味する(ようにサーバ側でも処理を書く)ので、ユーザにメッセージを表示しています。
alert('送信しました。ありがとうございます。');
alertはメッセージポップアップをユーザに表示する処理です。各評価式の中では
alert('タイトルが入力されていません。');
このように、入力内容の不備を指摘する内容になっています。
そしてelseに入った時に行うもう一つの処理が
location.href="/thread/" + data + "/";
これです。これはページを遷移させる処理です。
これには2つの意味があり、
・登録した後も入力フォームに留まっていても意味がない
・登録が完了したことを画面描画で明確にユーザに示す必要がある
という問題を解消するためです。
画面描画で明確にユーザに登録完了を示す、ということは?・・・もうお分かりですね。遷移先のページはスレッドの詳細ページです。
でも今はまだ未実装なので、表示できません。
スレッドの登録にはあとサーバ側の処理が必要です。このページのタイトルにある「登録の準備」としてはここまでです。
おわりに
今回も新しい知識が盛りだくさんだったと思います。
つかれましたね(ノД`)・゜・。大丈夫ですかね(*´Д`)
ソースコードの量が多いときはファイルを渡すようにしていますが、ダウンロードしてからそれを見本に手打ちしていただいても構いません。
手打ちすると、どこかのタイプミスのせいでちゃんと動かない!という問題が発生するかもしれませんが、それもプログラミング初心者あるあるでして、醍醐味のようなものと前向きにとらえてください(笑)
今回はクライアントサイドからサーバサイドにデータを送るところ、また処理が返ってきたところの動きを学習しました。次回はサーバ側の処理をやりましょう。
今回の範囲は次回・次々回やる分とセットなのでちょっと物足りなかったかもしれません・・・(´Д`) でもボリューム的には結構ありました(∩´∀`)∩
では、ゆっくり休んで次に備えてください( *´艸`)
今回もありがとうございました(∩´∀`)∩