PHP+SQLiteでTwitterのようなアプリをつくる(1)の続きです。前回はログイン機能を実装したので、今回は投稿してその投稿を表示させる機能を実装します。
Contents
投稿されたデータ用のテーブルを定義する
投稿されたデータ用のテーブルを定義する関数を定義します。リツイートや返信ではない投稿の場合、rt_targetとreply_targetはそれぞれ-1を設定します。
functions.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
function CreateArticleTable($db){ $text = "CREATE TABLE if not exists ARTICLE_TABLE ("; $text .= "id integer primary key autoincrement,"; // プライマリキー $text .= "user_id text,"; // 投稿したユーザーのID $text .= "text text,"; // 投稿された文字列 $text .= "create_at text,"; // 投稿された時刻 $text .= "update_at text,"; // 更新された時刻 $text .= "rt_target integer,"; // リツイートであればその対象の投稿のプライマリキー $text .= "reply_target text,"; // 返信であればその対象の投稿のプライマリキー $text .= "fabo_count integer,"; // いいねの数 $text .= "rt_count integer)"; // リツイートの数 $sql = $text; $db->query($sql); } |
データベースに投稿を保存する
投稿されたときに、その投稿をデータベースに保存する関数を示します。
テーブルが生成されていないかもしれないのでその場合は生成します。ログインされた状態でない場合やPOSTされたデータのなかに’text’が存在しない場合は、なにもしません。
投稿にアップロードされたファイルがあるかもしれないので、アップロードが成功した場合は画像を表示するためのHTMLタグを生成していっしょにデータベースに保存します。また投稿された文字列のなかにはおかしなスクリプトが混入しているかもしれないのでエスケープ処理をおこないます(世の中、善人ばかりではありません)。
そしてSQLインジェクション攻撃に備えてプリペアドステートメントを使います。繰り返しになりますが、世の中にいる人は善人ばかりではありません。
functions.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
function AddArticle($rt_target, $reply_target){ // ログインされた状態でない場合はなにもしない if (!isset($_SESSION['user_id'])) return; // POSTされたデータのなかに'text'が存在しない場合はなにもしない if (!isset($_POST['text'])) return; $user_id = $_SESSION['user_id']; $text = $_POST['text']; $db_path = GetDbPath(); $db = new PDO("sqlite:{$db_path}"); // テーブルが生成されていないかもしれない。 // 生成されていない場合は生成する。されている場合はなにもしない。 CreateArticleTable($db); // 投稿にアップロードされたファイルがあるかもしれない // 元ファイル名の先頭にアップロード日時を加える // 事前にimagesディレクトリを作成しておかないとエラーになるので注意 $image_path = './images/'. date("Y-md-His")."-".$_FILES['file_upload']['name']; $upload_ok = false; if(move_uploaded_file($_FILES['file_upload']['tmp_name'], $image_path)) { // PHPエラーを非表示 error_reporting(0); if (imagecreatefromstring(file_get_contents($image_path)) !== false) $upload_ok = true; else { // 画像でないなら削除 unlink($image_path); } } // おかしなスクリプトが投稿されるかもしれないのでエスケープする // 画像はHTMLタグとして扱わなければならないので表示されるときではなく、 // データベースへ保存する段階でエスケープする $text = htmlspecialchars($text, ENT_QUOTES | ENT_HTML5, 'UTF-8'); // 画像ファイルのアップロードが成功した場合は、画像を表示させるためのHTMLタグを生成する if($upload_ok) $text .= '<p><img src="' . $image_path . '" class = "article-image"></p>'; // 投稿時刻 $now = date("Y-m-d H:i:s"); // 投稿されたばかりなので、いいねとRTの数は 0 である $fabo_count = 0; $rt_count = 0; // SQLインジェクション攻撃に注意!! $sql = "INSERT INTO ARTICLE_TABLE (user_id, text, rt_target, reply_target, create_at, update_at, fabo_count, rt_count)"; $sql .= " VALUES (:user_id, :text, :rt_target, :reply_target, :create_at, :update_at, :fabo_count, :rt_count)"; $stmt = $db->prepare($sql); $stmt->bindValue(':user_id', $user_id); $stmt->bindValue(':text', $text); $stmt->bindValue(':rt_target', $rt_target); $stmt->bindValue(':reply_target', $reply_target); $stmt->bindValue(':create_at', $now); $stmt->bindValue(':update_at', $now); $stmt->bindValue(':fabo_count', $fabo_count); $stmt->bindValue(':rt_count', $rt_count); $stmt->execute(); // リツイートであればリツイート対象のリツイート数をインクリメントしなければならない UpdateRtCount($db, $rt_target, true); // 終わり $db = null; } |
表示するために必要な自作関数
データベースに保存されているリツイート数を更新する関数をしめします。プライマリキーが第二引数のものを変更します。第三引数がtrueなら1増加、falseなら1減少です。
functions.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
function UpdateRtCount($db, $article_id, $increment){ $sql = 'SELECT rt_count FROM ARTICLE_TABLE WHERE id = :article_id'; $stmt = $db->prepare($sql); $stmt->bindValue(':article_id', $article_id); $stmt->execute(); $row = $stmt->fetch(); if(is_array($row) == true){ if($increment == true) $rt_count = $row['rt_count'] + 1; else $rt_count = $row['rt_count'] - 1; $sql = "UPDATE ARTICLE_TABLE SET rt_count = :rt_count WHERE id = :article_id"; $stmt = $db->prepare($sql); $stmt->bindValue(':article_id', $article_id); $stmt->bindValue(':rt_count', $rt_count); $stmt->execute(); return $rt_count; } } |
GetUserNameFromUserID関数はユーザーIDからユーザー名を返します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
function GetUserNameFromUserID($db, $user_id){ $sql = 'SELECT user_name FROM USER_TABLE WHERE user_id = :user_id'; $stmt = $db->prepare($sql); $stmt->bindValue(':user_id', $user_id); $stmt->execute(); $row = $stmt->fetch(); if(is_array($row) == true) return $row['user_name']; else return ''; } |
GetUserIDFromArticleID関数は投稿のプライマリキーから投稿者のユーザーIDを取得します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
function GetUserIDFromArticleID($db, $article_id){ $sql = 'SELECT user_id FROM ARTICLE_TABLE WHERE id = :id'; $stmt = $db->prepare($sql); $stmt->bindValue(':id', $article_id); $stmt->execute(); $row = $stmt->fetch(); if(is_array($row) == true) return $row['user_id']; else return ''; } |
GetReplyCount関数は投稿のプライマリキーから返信の数を取得します。
1 2 3 4 5 6 7 8 9 |
function GetReplyCount($db, $reply_target){ $sql = 'SELECT id FROM ARTICLE_TABLE WHERE reply_target = :reply_target'; $stmt = $db->prepare($sql); $stmt->bindValue(':reply_target', $reply_target); $stmt->execute(); $rows = $stmt->fetchAll(); return count($rows); } |
GetRowFromArticleID関数は引数で渡された値とプライマリキーが一致する投稿のレコードを返します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
function GetRowFromArticleID($db, $article_id){ $sql = 'SELECT * FROM ARTICLE_TABLE WHERE id = :id'; $stmt = $db->prepare($sql); $stmt->bindValue(':id', $article_id); $stmt->execute(); $row = $stmt->fetch(); if(is_array($row) == true) return $row; else return null; } |
投稿を表示させる
ShowArticle関数は投稿をページ上に表示します。
表示させるのは投稿者名、投稿された文字列、アップロードされた画像ファイル、投稿の種類(「RT」か「返信」か普通の投稿か?)、「いいね」「RT」「返信」「削除」ボタンです。また投稿が「RT」や「返信」の場合はその対象がなにかもわかるようにいっしょに表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
function ShowArticle($db, $article_id, $show_reply_target, $show_footer){ $sql = 'SELECT * FROM ARTICLE_TABLE WHERE id = :id'; $stmt = $db->prepare($sql); $stmt->bindValue(':id', $article_id); $stmt->execute(); $row = $stmt->fetch(); if(is_array($row) == true){ $user_name = GetUserNameFromUserID($db, $row['user_id']); $text = $row['text']; echo '<div id = "article-'. $row['id'] . '" class="shadow p-3 mb-3 bg-body rounded">' . "\n"; // 投稿が「RT」や「返信」であればそのように表示する if(is_numeric($row['rt_target']) && $row['rt_target'] != -1) echo '<div><a href="./?user='.$row['user_id'].'">'.$user_name.'</a> さんが RT しました<span class = "ms-3">'.$row['create_at'].'</span></div>' . "\n"; else if(is_numeric($row['reply_target']) && $row['reply_target'] != -1) echo '<div><a href="./?user='.$row['user_id'].'">'.$user_name.'</a> さんが 返信 しました<span class = "ms-3">'.$row['create_at'].'</span></div>' . "\n"; else echo '<div><a href="./?user='.$row['user_id'].'">'.$user_name.'</a> <span class = "ms-3">'.$row['create_at'].'</span></div>' . "\n"; echo '<div><pre class = "mt-2">'.$text.'</pre></div>' . "\n"; // 投稿が「RT」であればその対象も表示する if(is_numeric($row['rt_target']) && $row['rt_target'] != -1) ShowRtTarget($db, $row); // 投稿が「返信」であり $show_reply_target == true ならその対象も表示する if(is_numeric($row['reply_target']) && $row['reply_target'] != -1 && $show_reply_target) ShowReplyTarget($db, $row); // $show_footer == true なら「いいね」「RT」「返信」「削除」ボタンも表示する if($show_footer) ShowArticleFooter($db, $row); echo '</div>' . "\n"; } } |
投稿がRTである場合、RT元も表示させます。ただしRT元がすでに投稿者によって削除されている可能性もあるので、対象が存在するかどうかで処理を切り分けています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
function ShowRtTarget($db, $row){ echo '<div class="ms-1">' . "\n"; echo '<div class="shadow p-3 mb-3 bg-body rounded">' . "\n"; // リツイート元が存在する $target_row = GetRowFromArticleID($db, $row['rt_target']); if($target_row != null){ $text = $target_row['text']; $user_id = $target_row['user_id']; $user_name = GetUserNameFromUserID($db, $target_row['user_id']); $link_url = './?article=' . $target_row['id']; echo '<div>'; echo '<a href="./?user='. $user_id. '">' .$user_name. '</a>'; echo '<span class = "ms-3">'.$target_row['create_at'].'</span>' . "\n"; echo '<span class = "ms-3"><a href="' . $link_url .'">RTされた投稿を表示</a></span>' . "\n"; echo '</div>' . "\n"; echo '<div><pre class = "mt-2">'.$target_row['text'].'</pre></div>' . "\n"; echo '<div class = "text-info b">RT: '.$target_row['rt_count'].'</div>' . "\n"; } else { echo "<div><pre>RT元は削除されています。</pre></div>" . "\n"; } echo "</div>" . "\n"; echo "</div><!-- /.left -->" . "\n"; } |
ShowReplyTarget関数は投稿が返信である場合、返信元を表示する処理をおこないます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
function ShowReplyTarget($db, $row){ echo '<div class="ms-1">' . "\n"; echo '<div class="shadow p-3 mb-3 bg-body rounded">' . "\n"; // 返信先が存在する $target_row = GetRowFromArticleID($db, $row['reply_target']); if($target_row != null){ $text = $target_row['text']; $user_id = $target_row['user_id']; $user_name = GetUserNameFromUserID($db, $target_row['user_id']); $link_url = './?article=' . $target_row['id']; echo '<div>'; echo '<a href="./?user='. $user_id. '">' .$user_name. '</a>'; echo '<span class = "ms-3">'.$target_row['create_at'].'</span>' . "\n"; echo '<span class = "ms-3"><a href="' . $link_url .'">返信先を表示</a></span>' . "\n"; echo '</div>' . "\n"; echo '<div><pre class = "mt-2">'.$target_row['text'].'</pre></div>' . "\n"; echo '<div class = "text-info b">RT: '.$target_row['rt_count'].'</div>' . "\n"; } else { echo "<div><pre>返信先の投稿は削除されています。</pre></div>" . "\n"; } echo "</div>" . "\n"; echo "</div><!-- /.left -->" . "\n"; } |
投稿の下に「いいね」「削除」などのボタンを表示する処理を示します。RTと返信の数もすでに示した関数で取得していっしょに表示させています。
DoesFaborite関数は現在ログインしているユーザーがその記事をいいねしているかどうかを返します(後述)。そしてその結果によってボタンの表示色を変えます。「削除」ボタンは現在ログインしているユーザーによる投稿でないと表示されません。
ボタンをクリックしたらその処理をするページへ遷移したりJavaScriptの関数が呼び出されます。このときの引数も表示させています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
// DoesFaborite関数の詳細はあとまわしにします // とりあえず常にfalseを返す関数として定義します。 function DoesFaborite($db, $article_id){ return false; } function ShowArticleFooter($db, $row){ $fabo_count = $row['fabo_count']; // いいねの数を取得(空文字列なら0とみなす) if($fabo_count == '') $fabo_count = 0; echo '<button type="button" '; // 現在ログインしているユーザーがその記事をいいねしている場合はボタンの表示色を変える // 「いいね」ボタンがクリックされたら favorite(XX)関数が呼び出される if(DoesFaborite($db, $row['id'])) echo 'class="btn btn-dark fabo-btn-' . $row['id'] . '" onclick = "favorite(' . $row['id'] .')">'; else echo 'class="btn btn-outline-dark fabo-btn-' . $row['id'] . '" onclick = "favorite(' . $row['id'] .')">'; echo 'いいね <span class = "fabo-' . $row['id'] . '">'. $fabo_count .'</span></button>' . "\n"; // 「RT」ボタン // 「RT」ボタンがクリックされたら ./?rt=XX へ遷移する $rt_count = $row['rt_count']; if($rt_count == '') $rt_count = 0; $rt = "'./new.php?rt={$row['id']}'"; $rt = "'./?rt={$row['id']}'"; echo '<button class="btn btn-outline-dark ms-2" onclick = "location.href =' .$rt .'">RT '; echo '<span id = "rt-' . $row['id'] . '">'. $rt_count.'</span></button>' . "\n"; // 「返信」ボタン // 「RT」ボタンがクリックされたら ./?article=XX へ遷移する $reply_count = GetReplyCount($db, $row['id']); if($reply_count == '') $reply_count = 0; echo '<span><a type="button" '; echo 'class="btn btn-outline-dark ms-2" id = "res-btn-' . $row['id'] . '" href = "./?article=' . $row['id'] .'">'; echo '返信をみる ' .$reply_count . '</a></span>' . "\n"; // 「削除」ボタン // 「削除」ボタンがクリックされたら ./?delete=XX へ遷移する if (isset($_SESSION["user_id"]) && GetUserIDFromArticleID($db, $row['id']) == $_SESSION["user_id"]) echo '<span><a type="button" class="btn btn-danger ms-4" href="./?delete='.$row['id'].'">削除</a></span>'; } |
すべてのユーザーのすべての投稿を表示する処理を示します。
1 2 3 4 5 6 7 8 |
function ShowAllArticles($db){ $sql = 'SELECT id FROM ARTICLE_TABLE ORDER BY id desc'; $stmt = $db->query($sql); $rows = $stmt->fetchAll(); foreach ($rows as $row) ShowArticle($db, $row['id'], true, true); } |
特定のユーザーのすべての投稿を表示する処理を示します。
1 2 3 4 5 6 7 8 9 10 |
function ShowUserArticles($db, $user_id){ $sql = 'SELECT id FROM ARTICLE_TABLE WHERE user_id = :user_id ORDER BY id desc'; $stmt = $db->prepare($sql); $stmt->bindValue(':user_id', $user_id); $stmt->execute(); $rows = $stmt->fetchAll(); foreach ($rows as $row) ShowArticle($db, $row['id'], true, true); } |
特定の投稿に対するすべての返信を表示する処理を示します。
1 2 3 4 5 6 7 8 9 10 |
function ShowReplies($db, $reply_target_id){ $sql = 'SELECT id FROM ARTICLE_TABLE WHERE reply_target = :id'; $stmt = $db->prepare($sql); $stmt->bindValue(':id', $reply_target_id); $stmt->execute(); $rows = $stmt->fetchAll(); foreach ($rows as $row) ShowArticle($db, $row['id'], false, true); } |
ShowArticles関数はユーザーが現在アクセスしているページによって適切なかたちで投稿を表示します。
/?user=XX なら新規投稿用のフォームそのユーザーのすべての投稿を
/?article=XX ならその投稿と返信用のフォームとそれに対するすべての返信を
/?rt=XX ならその投稿とRT用のフォームを
/?delete=XX ならその投稿と削除用のボタンを
/ のあとになにもつかない場合は新規投稿用のフォームとすべてのユーザーのすべての投稿を表示させます。
require_once(‘new-form.php’);としていますが、new-form.phpの内容は後述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
function ShowArticles($db){ if(isset($_GET['user'])){ if(isset( $_SESSION["user_id"])){ $form_parameter = ''; $form_header = '<h3>新規投稿</h3>'; require_once('new-form.php'); } ShowUserArticles($db, $_GET['user']); } else if(isset($_GET['article'])){ ShowArticle($db, $_GET['article'], true, false); if(isset( $_SESSION["user_id"])){ $form_parameter = '?reply_id=' . $_GET['article']; $form_header = '<h3>上の投稿に返信する</h3>'; require_once('new-form.php'); } else echo '<p class = "mt-5 mb-3">返信するにはログインが必要です<p>'; echo '<h3 class = "mb-3">この投稿に対する返信の一覧</h3>'; ShowReplies($db, $_GET['article']); } else if(isset($_GET['rt'])){ if(isset( $_SESSION["user_id"])){ echo '<h2>リツイートする</h2>'; ShowArticle($db, $_GET['rt'], true, false); $form_parameter = '?rt_id=' . $_GET['rt']; $form_header = '<h3>上の投稿をRTする</h3>'; require_once('new-form.php'); } else { echo 'RT するときはログインしてください。'; } } else if(isset($_GET['delete'])){ if(isset( $_SESSION["user_id"])){ ShowArticle($db, $_GET['delete'], true, false); echo '<p class = "b mt-5">投稿を削除しようとしています。削除すると元には戻せません。</p>'; echo '<p><a class="btn btn-danger" href="./delete.php?id='.$_GET['delete'].'">削除する</a></p>'; } else { echo 'ログインしてください。削除できるのは自分の投稿だけです。'; } } else{ if(isset( $_SESSION["user_id"])){ $form_parameter = ''; $form_header = '<h3>新規投稿</h3>'; require_once('new-form.php'); } ShowAllArticles($db); } } |
ShowContents関数はページにコンテンツを表示します。
1 2 3 |
function ShowContents($db){ ShowArticles($db); } |
ShowHeader関数はページ上部にログインしているかどうか? ログイン、ログアウト用のリンクを表示させる関数です。
1 2 3 4 5 6 7 8 9 10 |
function ShowHeader(){ echo '<p id = "header">'; if(isset( $_SESSION["user_id"]) ){ echo $_SESSION['user_id'] . '<span class = "ms-1">でログインしています。</span><span class = "ms-3">ももったー?? から <a href="logout.php">ログアウト</a></span>'; } else { echo 'ログインしていません。<span class = "ms-3">ももったー?? に <a href="login-form.php">ログイン</a></span> <span class = "ms-3"><a href="signup.php">新規会員登録</a></span>'; } echo '</p>' . "\n"; } |
index.php
トップページにアクセスしたら投稿が表示されます。index.phpは以下のようにします。
index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<?php require_once('functions.php'); session_start(); ?> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>鳩でもわかるTwitterもどき</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> <link rel="stylesheet" href="./style.css" type="text/css" media="all" /> </head> <body> <?php ShowHeader(); ?> <div id = "main"> <?php $db_path = GetDbPath(); $db = new PDO("sqlite:{$db_path}"); CreateArticleTable($db); ShowContents($db); $db = null; ?> </div> <script src = "./app.js"></script> </body> </html> |
style.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
body { margin-top: 0px; margin-left: 0px; margin-right: 0px; } #header { background-color: #000; margin-top: 0px; margin-left: 0px; margin-right: 0px; padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 20px; color: #aaa; } #header a { color: #0ff; font-weight: bold; } #header a:hover { color: #f00; font-weight: bold; } .article-image { max-width : 300px; } .prof-image { max-width : 300px; } #file-image { max-width : 300px; } .b {font-weight: bold;} a { color: #00f; font-weight: bold; } a:hover { color: #f00; } #main { padding-left: 20px; } body {font-family: sans-serif; } h1 { font-size: 200%; } h2 { font-size: 150%; } h3 { font-size: 120%; } h1, h2, h3 { font-weight: bold; } #textarea { margin: 5px 0 15px 0; } .post-new { width:200px; margin: 20px 0 40px 0; } pre { font-size: 1em; } |
JavaScript部分
画像をアップロードしようとしているときにどんな画像なのか表示する処理と、いいねをクリックしたときの処理をおこなっています。いいねに関する処理の詳細は次回にします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
window.onload = () => { const $fileName = document.getElementById('file-name'); const $image = document.getElementById('file-image'); const $imageCheck = document.getElementById('image-check'); if($fileName != null){ $fileName.addEventListener('change', () => { file = $fileName.files[0]; let fileReader = new FileReader(); fileReader.readAsDataURL(file); fileReader.onloadend = () => { $image.src = fileReader.result; $image.onload = () => { $imageCheck.innerText = 'この画像が投稿されます。'; } $image.onerror = () => { $imageCheck.innerText = 'これは画像ファイルではありません。'; } }; }); } } async function favorite(id){ let res = await fetch("./favorite.php?id=" + id); let ret = await res.text(); let els = document.getElementsByClassName("fabo-" + id); let btns = document.getElementsByClassName("fabo-btn-" + id); if(!isNaN(ret)){ let old = Number(els[0].innerText); if(Number(ret) > old){ for(let i=0; i<btns.length; i++){ btns[i].classList.remove('btn-outline-dark'); btns[i].classList.add('btn-dark'); } } else { for(let i=0; i<btns.length; i++){ btns[i].classList.remove('btn-dark'); btns[i].classList.add('btn-outline-dark'); console.log('減少'); } } for(let i=0; i<els.length; i++){ els[i].innerText = ret; } } else alert("「いいね」をするにはログインしてください"); } |
new-form.php
投稿用のフォームを表示するために必要な部分です。一応、字数制限しています。
new-form.php
1 2 3 4 5 6 7 8 |
<div class = "mt-5"><?php echo $form_header; ?></div> <form action="./new-post.php<?php echo $form_parameter; ?>" method="post" enctype="multipart/form-data" style = "margin-bottom: 20px"> <div id = "textarea"><textarea name="text" cols="50" rows="5" maxlength ="250" required></textarea></div> <input type="submit" value="投稿する"> <span class = "left"><input name="file_upload" type="file" id = "file-name"></span> </form> <p><img src="" id="file-image" /></p> <p id="image-check"></p> |
投稿ボタンがクリックされたときの処理
投稿ボタンがクリックされたらnew-post.phpへポストされます。引数を適切に処理して
new-post.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<?php require_once('functions.php'); session_start(); // ログインしていないユーザーであればなにもしない if (!isset($_SESSION['user_id'])) exit; $rt_id = -1; $reply_id = -1; // RTとして投稿された if (isset($_GET['rt_id'])) $rt_id = $_GET['rt_id']; // 返信として投稿された if (isset($_GET['reply_id'])) $reply_id = $_GET['reply_id']; // データベースに保存する AddArticle($rt_id, $reply_id); // 返信として投稿されたなら返信一覧のページへ // そうでないなら各ログインユーザーのページにリダイレクトさせる if (isset($_GET['reply_id'])) header("Location: ./?article=".$_GET['reply_id']); else header("Location: ./?user=".$_SESSION['user_id']); ?> |