Developer

魁!小野の塾 PHPで簡単なプログラムを作ってみようの巻 第9話
2021.01.01
Lv2

魁!小野の塾 PHPで簡単なプログラムを作ってみようの巻 第9話

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 highlight=”50-58″] <?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();
?>
[/php]

削除するように、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要素を追加し、削除用のパラメータを埋めていきます。

削除機能追加(抜粋)
[html highlight=”14,16-17,22″] <?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 } ?>
[/html]

FORM要素を追加し、hiddenを2つ追加します。(action, id)actionは、固定値でdeleteを入れておきます。
idは数字で、特に入力値を入れるわけでもないので、htmlentitiesをつける必要もないのですが、出力する場合は必ずつけると癖をつけると忘れないで済みます。(忘れるとイタイデスカラ)

FORM要素を追加したくない場合は、Javascriptを書く必要があります。その場合はもろもろ変更する必要があったりします。

Javascriptを利用する場合(抜粋)
[html highlight=”3,9,20-30″] <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>
[/html]

登録のFORM要素にhiddenを追加。名前はidです。
ボタンを押下した場合に、data-* グローバル属性を定義してあると、情報の取得が簡単に行えます。
scriptの内容ですが、data-id属性が定義されている要素を対象に、クリックした場合、以下を行います。

  1. クリックしたボタンに定義してある、data-idの値を取得(要素.data(‘id’))
  2. FORM要素の最初を取得(登録用フォーム)
  3. actionの値をdeleteに変更
  4. idの値を対象idに変更
  5. FORM要素をサブミットします。

Javascriptで行うか、FORM要素で行うかは趣味の問題なので、どちらでも問題なく動きます。
保守性的には、FORM要素で書いたほうが、初心者の受けは良いです。

最後の小言

ざっくりと進めてまいりましたが、これで完成となります。
内容は色々な情報が入り交じり、難しそうに見えるのですが、作業自体は4時間程度で作成できるかと思います。
変なこだわりがあるとHTMLを触り続けてしまうので、そこは気を付けましょう。(特にアニメーション。。。。)

慣れてくると、色々なCDNを駆使できるようになるので、あとは何度も作ることをお勧めします。
テーブルの項目数やデータ型を増やして、作り直すことで、どこがどのように変更すれば出来るかなどが分かるはずです。

出来るだけ、記事の途中にあるリンクを先をみて、なるべく覚えるようにしてください。
数回記事を読みながら、リンククリックして、各サイトを読むだけで、かなりレベルが上がるかと思います。

実際の業務で利用する画面では、項目数が多いので、エラーチェックも含めて、かなりげんなりすること間違えなしです!
出来るだけ早くなれることをお勧め致します。

今回の簡単な掲示板作成に関しては、これにて終了です。
お疲れ様でした。

魁!小野の塾