PHPで簡単なプログラムを作ってみよう 第9話
初心者向け、PHPプログラム構築講座です。
初心者といっても、PHPの勉強を少し行い、LAMP環境が自分で構築できるレベルを対象とします。
まったくの初心者の場合は、わからない部分が出てくると思います。
できるだけ細かく説明は入れていきますが、説明がわからない場合は、PHPやMySQLの初心者講座をご覧ください。
対象のスキルレベル
- LAMP環境の構築
- PHP言語が読める
- HTML, CSS, Javascriptが少しわかる
- Bootstrapのドキュメントをみて、HTMLが書ける
- CDNを理解している
構築環境
- Windows10
- XAMPP(PHP7.3.2, MariaDB 10.1.38)
削除機能の実装
最後に削除機能を実装していきます。
action で指定している登録部分に、削除のロジックを追加していきます。
<?php // db resource $db = new mysqli('localhost', 'root', '', 'pjin'); $db->set_charset("utf8"); // $_POST -> $request $request = [ 'author' => $_POST['author'] ?? '', 'content' => $_POST['content'] ?? '', 'action' => $_POST['action'] ?? '' ]; // create or delete $errors = []; switch($request['action']){ case 'create': // error check if(empty($request['author'])){ $errors['author'][] = '名前を入力して下さい。'; } if(mb_strlen($request['author']) > 128){ $errors['author'][] = '名前は128文字以内で入力して下さい。'; } if(empty($request['content'])){ $errors['content'][] = '内容を入力して下さい。'; } if(mb_strlen($request['content']) > 65535){ $errors['content'][] = '名前は65,535文字以内で入力して下さい。'; } if(count($errors) > 0){ // エラーがあれば終了 break; } // 登録処理 $sql = "insert into board(author, content) values (?, ?)"; if($stmt = $db->prepare($sql)){ $stmt->bind_param("ss", $request['author'], $request['content']); $stmt->execute(); $stmt->close(); // 登録後に空にします。 $request = [ 'author' => '', 'content' => '' ]; } break; case 'delete'; // 削除処理 $sql = "delete from board where id = ?"; if($stmt = $db->prepare($sql)){ $stmt->bind_param("i", $_POST['id']); $stmt->execute(); $stmt->close(); } break; } // 検索処理 $rs = []; $sql = "select * from board order by id desc"; if($stmt = $db->prepare($sql)){ $stmt->execute(); $stmt->bind_result($id, $createdAt, $author, $content); while($stmt->fetch()){ $rs[] = [ 'id' => $id, 'createdAt' => $createdAt, 'author' => $author, 'content' => $content ]; } $stmt->close(); } // db resource close $db->close(); ?>
削除するように、boardテーブルの主キーであるidをPOSTで送信し、対応するidの行を削除します。
このプログラムでは、actionがない場合は、検索処理を実施し、actionがある場合は、登録又は削除が行われることを想定しています。
更新がある場合は、このaction部分に追加していくようになります。(※今回は作成しませんが。。)
特に削除する対象をチェックすることは行いません。また、論理削除ではなく、物理削除しています。
論理削除の場合は、is_delete や delete_at などのフラグや日時を入れて制御します。
物理削除の場合は、多重度が上がった場合に、先に他の誰かが削除したとしても、SQLの実行でエラーになることはありません。
多重度を考慮する場合は、更新日時などを参照して、画面に表示した時刻と比較して新しくなっているかを確認し、新しい場合はエラーを出力します。(楽観排他)
例えば、画面出力時刻が、2021/03/23 10:20:03 だったとします。これをHTMLのhiddenで埋めておきます。
更新又は削除の処理を実行した場合に、一緒にサーバへ送付後、対象レコードの更新日時を参照します。
更新日時が、2021/03/23 10:25:28 だった場合は、誰かほかの方が、操作中に更新したことが分かります。
この場合に更新するかはプロジェクトごとに異なりますが、先勝ちの場合はエラーとして処理します。
HTML部分の修正
削除ボタンの周りに、FORM要素を追加し、削除用のパラメータを埋めていきます。
<?php foreach($rs as $row){ ?> <div class="card"> <div class="card-header"> <div class="row"> <div class="col-sm-6"> <strong><?php echo htmlentities($row['author']) ?></strong> </div> <div class="col-sm-6 text-right"> <small><?php echo date('Y-m-d H:i:s ', strtotime($row['createdAt'])) ?></small> </div> </div> </div> <div class="card-body"> <form action="<?php echo $_SERVER['SCRIPT_NAME'] ?>" method="POST"> <p class="float-right"> <input type="hidden" name="action" value="delete"> <input type="hidden" name="id" value="<?php echo htmlentities($row['id']) ?>"> <button type="submit" class="btn btn-outline-danger btn-sm"> <i class="far fa-trash-alt"></i> 削除 </button> </p> </form> <p class="card-text"> <?php echo nl2br(htmlentities($row['content'])) ?> </p> </div> </div> <div class="mt-3"></div> <?php } ?>
FORM要素を追加し、hiddenを2つ追加します。(action, id)actionは、固定値でdeleteを入れておきます。
idは数字で、特に入力値を入れるわけでもないので、htmlentitiesをつける必要もないのですが、出力する場合は必ずつけると癖をつけると忘れないで済みます。(忘れるとイタイデスカラ)
FORM要素を追加したくない場合は、Javascriptを書く必要があります。その場合はもろもろ変更する必要があったりします。
<form action="<?php echo $_SERVER['SCRIPT_NAME'] ?>" method="POST"> <input type="hidden" name="action" value="create"> <input type="hidden" name="id" value=""> [省略] <div class="card-body"> <p class="float-right"> <button class="btn btn-outline-danger btn-sm" data-id="<?php echo htmlentities($row['id']) ?>"> <i class="far fa-trash-alt"></i> 削除 </button> </p> <p class="card-text"> <?php echo nl2br(htmlentities($row['content'])) ?> </p> </div> [省略] <script> $(function(){ $('[data-id]').on('click', function(){ var id = $(this).data('id'); var $form = $('form:first'); $form.find('[name=action]').val('delete'); $form.find('[name=id]').val(id); $form.submit(); }); }); </script>
登録のFORM要素にhiddenを追加。名前はidです。
ボタンを押下した場合に、data-* グローバル属性を定義してあると、情報の取得が簡単に行えます。
scriptの内容ですが、data-id属性が定義されている要素を対象に、クリックした場合、以下を行います。
- クリックしたボタンに定義してある、data-idの値を取得(要素.data(‘id’))
- FORM要素の最初を取得(登録用フォーム)
- actionの値をdeleteに変更
- idの値を対象idに変更
- FORM要素をサブミットします。
Javascriptで行うか、FORM要素で行うかは趣味の問題なので、どちらでも問題なく動きます。
保守性的には、FORM要素で書いたほうが、初心者の受けは良いです。
最後の小言
ざっくりと進めてまいりましたが、これで完成となります。
内容は色々な情報が入り交じり、難しそうに見えるのですが、作業自体は4時間程度で作成できるかと思います。
変なこだわりがあるとHTMLを触り続けてしまうので、そこは気を付けましょう。(特にアニメーション。。。。)
慣れてくると、色々なCDNを駆使できるようになるので、あとは何度も作ることをお勧めします。
テーブルの項目数やデータ型を増やして、作り直すことで、どこがどのように変更すれば出来るかなどが分かるはずです。
出来るだけ、記事の途中にあるリンクを先をみて、なるべく覚えるようにしてください。
数回記事を読みながら、リンククリックして、各サイトを読むだけで、かなりレベルが上がるかと思います。
実際の業務で利用する画面では、項目数が多いので、エラーチェックも含めて、かなりげんなりすること間違えなしです!
出来るだけ早くなれることをお勧め致します。
今回の簡単な掲示板作成に関しては、これにて終了です。
お疲れ様でした。