前回はカテゴリーや支払い方法など選択項目を画面から追加する機能を実装しました。
今回は登録している項目を編集したり削除したりする機能を実装していきます。
↓前回の記事はこちら
更新機能の実装
まずは流れを確認します。
【更新機能の流れ】
①編集ボタンを押したら、更新入力要素を表示&追加入力要素を非表示
②編集ボタンを押されたデータをinput要素に復元
③UPDATE文で情報を更新する
編集ボタン押下で更新入力と追加入力の表示切り替え
現在選択項目編集ページには項目を追加する要素のみが表示されています。
これを初期状態=追加入力要素を表示、編集ボタン押下=更新入力要素を表示に切り替える形にします。
流れは編集ボタンにonclick属性をセットし、JavaSciptの関数でclassの付与と削除を行います。
まずは編集ボタン(item-edit.php90行目付近)にonclick属性を追加します。
<button onclick="onClickUpdate();"><i class="fa-solid fa-pen"></i></button> <!--onclick属性のみ表示-->
引数はJavaScriptで関数を作成したあとに設定するので現段階では空でOKです。
それではonClickUpdate関数をfunctions.jsに作成します。
const onClickUpdate = () => {
const itemAddElement = document.getElementById('itemAddElement'); //追加formを取得
const itemEditElement = document.getElementById('itemEditElement'); //更新formを取得
itemAddElement.classList.add('hide'); //追加formにhideクラスを付与
itemEditElement.classList.add('show'); //更新formにshowクラスを付与
}
すでにCSSで表示非表示の指定はしているので、今回はstyle.cssに書き加える必要はありません。
以上で追加入力と更新入力要素の表示切り替えができるようになります。
編集ボタンを押下で更新入力要素が表示され、キャンセル押下で元の画面(=追加入力要素が表示された状態)に戻ります。
編集ボタンを押されたデータをinput要素に復元
編集ボタン押下で更新入力要素を表示できましたが、どの項目を編集できるようになったかわかりにくいので、input要素に編集ボタンを押したデータを復元します。
1つ前のステップで作成したonClickUpdate関数に以下の処理を追加します。
const updateId = document.getElementById('updateId'); //type=hiddenのidをセットするinputを取得する
const updateName = document.getElementById('updateName'); //更新項目入力要素を取得する
updateId.value = id; //idをセットするinputのvalueに引数idを挿入する
updateName.value = name; //更新入力inputに引数nameを挿入する
続いて引数を追加します。
const onClickUpdate = (id, name) => {
//処理内容省略
}
関数に引数を追加したので、onclickに設定している部分に引数を指定します。
<button onclick="onClickUpdate('<?php echo h($id); ?>', '<?php echo h($name); ?>');"> <!--onclick属性のみ表示-->
新しい処理や引数を追加することで、編集ボタンを押下した際、項目名が入力された状態で更新入力要素を表示することができます。
最後に2つ目のtype=hiddenのvalueにそのページのテーブル名を示す数値が挿入されるように、valueを指定します。
<!--124行目付近-->
<input type="hidden" name="id" id="updateId" value="">
<input type="hidden" name="editItem" value="<?php echo $editItem; ?>"> <!--valueに値を追加-->
UPDATE文で情報を更新する
それでは更新ボタンが押されたらデータベースの内容を入力した内容に書き換えるプログラムを記述します。
まずは「item-update.php」というファイルを作成し、共通ファイル読み込みプログラムを記述します。
<?php
require_once('./dbconnect.php');
include_once('./functions.php');
そして更新入力フォームのaction属性に、作成したitem-update.phpファイルを指定します。(item-edit.php120行目付近)
<form class="p-form p-form--cat-edit" id="itemEditElement" action="./item-update.php" method="POST">
続いてitem-updateで値を受け取りUPDATE文で更新するプログラムを記述します。
$table_list = ['spending_category', 'income_category', 'payment_method', 'creditcard', 'qr'];
$id = filter_input(INPUT_POST, 'id', FILTER_SANITIZE_SPECIAL_CHARS);
$editItem = filter_input(INPUT_POST, 'editItem', FILTER_SANITIZE_NUMBER_INT);
$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_SPECIAL_CHARS);
$table_name = $table_list[$editItem];
上記は値を受け取ったり、受け取った値をもとにSQLにセットする値を生成している部分です。
idやnameは受け取った値をそのまま使いますが、テーブル名は直接受け渡さず、以前も記述したようにテーブル名の配列を作り何番目のテーブルかを示す番号を受け取って、テーブル名を$table_nameにセットしています。
$sql = "UPDATE {$table_name} SET name=? WHERE id=?";
$stmt = $db->prepare($sql);
$stmt->bind_param('si', $name, $id);
if (!$stmt) :
header('Location: ./item-edit.php?editItem=' . $editItem . '&dataOperation=error');
exit();
endif;
$success = $stmt->execute();
if (!$success) :
header('Location: ./item-edit.php?editItem=' . $editItem . '&dataOperation=error');
exit();
endif;
header('Location: ./item-edit.php?editItem=' . $editItem . '&dataOperation=update');
exit();
上記は先ほど受け取ったり生成した値をもとにSQLでデータを更新し、元のページに戻すプログラムです。これまでは「sql_check()」でSQLのエラー処理をしていましたが、今回はただ処理を終了するのではなく、パラメータ付きのページに返したいので、個別に記述しています。
すべて正常に処理が行われた戻し先は、該当選択項目ページ番号とdataOperation=updateパラメータも付け加えた場所に戻しています。
最後にこのページでは「更新しました」というメッセージを出す要素を作成していないので、index.phpにあるメッセージモーダルを<main>の下に貼り付けます。
<!-- 操作完了コンテンツ -->
<?php if ($_GET['dataOperation'] && ($_GET['dataOperation'] === 'delete' || $_GET['dataOperation'] === 'update' || $_GET['dataOperation'] === 'error')) : ?>
<section class="p-section p-section__full-screen" id="doneOperateBox">
<div class="p-message-box <?php echo ($_GET['dataOperation'] === 'error') ? 'line-red' : 'line-blue'; ?>">
<p id="doneText">
<?php
if ($_GET['dataOperation'] === 'error') :
echo '正しく処理されませんでした';
elseif ($_GET['dataOperation'] === 'delete') :
echo '削除しました';
elseif ($_GET['dataOperation'] === 'update') :
echo '更新しました';
endif;
?>
</p>
<button class="c-button <?php echo ($_GET['dataOperation'] === 'error') ? 'c-button--bg-darkred' : 'c-button--bg-blue'; ?>" onclick="onClickOkButton();">OK</button>
</div>
</section>
<?php endif; ?>
<!-- //操作完了コンテンツ -->
ここでメッセージモーダルのOKを押すとindex.phpに戻ってしまいます。これはJavaScriptプログラム内「history.pushState(”, ”, url.pathname);」でurl.pathname(=item-edit.php)と指定され、パラメータがないので強制的にホーム画面へ戻っています。
ユーザー操作的には選択項目ページに戻したいので、この部分を引数にしてOKボタン押下後の戻るページを分けます。
まずはfunctions.js内のonClickOkButton関数を以下のように書き換えます。
const onClickOkButton = (param) => { //引数追加
const url = new URL(window.location.href);
url.searchParams.delete('dateOperation');
history.pushState('', '', url.pathname + param); //第三引数をパラメータ前までのURLに引数(パラメータ)を足したものに指定
location.reload();
}
続いてこの関数をonclick属性にセットしている部分に引数をセットしていきます。ホームページ(index.php)はパラメータを必要としないので特に修正はありませんが空白のままだとエラーが出てしまうので空文字をセットします。
<!--index.php 54行目付近-->
<button class="c-button <?php echo ($_GET['dataOperation'] === 'error') ? 'c-button--bg-darkred' : 'c-button--bg-blue'; ?>" onclick="onClickOkButton('');">OK</button>
一方選択項目ページはパラメータで内容を変えているので、パラメータ部分を引数にセットする必要があります。onclick属性の引数に「onclick=”onClickOkButton(‘?editItem=<?php echo $editItem; ?>’);”」を追記しました。
<!--item-edit.php 74行目付近-->
<button class="c-button <?php echo ($_GET['dataOperation'] === 'error') ? 'c-button--bg-darkred' : 'c-button--bg-blue'; ?>" onclick="onClickOkButton('?editItem=<?php echo $editItem; ?>');">OK</button>
以上でモダールメッセージのOKを押したあとの戻すページを分けることができるようになりました。
削除機能の実装
【削除機能の流れ】
①削除ボタンが押されたデータを取得しアラートを出す
②キャンセルが押されたら遷移を無効にする
③OKが押されたらDELETE文で削除する
プログラムの流れは以前実装したレコードの削除と同じです。
削除ボタン押下でアラート表示・キャンセル押下で遷移無効化
このイベントはすでに作成している「deleteConfirm関数」を使って実装します。
削除ボタンに以下のonclick属性とid属性を指定します。
<!--115行目付近-->
<a id="<?php echo 'item' . h($id); ?>" onclick="deleteConfirm('<?php echo h($name); ?>','<?php echo 'item' . h($id); ?>');">
これで削除ボタンを押下した際にアラートが表示され、キャンセルを押すと元の画面に戻ります。
続いてOKが押下された際の削除プログラムを実装します。
OKが押されたらDELETE文で削除する
削除プログラムの流れは、レコード削除の処理と似ているので、すでに作成しているdelete.phpに条件分岐等を加えて修正という形で実装していきます。
処理が異なる点
・SQL文
・処理後に戻す画面
以上2点が異なる処理となります。まずはそれぞれの削除ボタンにどのページの削除ボタンかを表すパラメータを追加して条件分岐の判断に使えるようにします。
※index.phpのスマホ表示用の削除ボタンにもパラメータを追加してください
<!--index.phpの削除ボタン 300行目付近と410行目付近(スマホ表示用)-->
<a href='./delete.php?id=<?php echo h($id); ?>&from=index'>
<!--item-edit.phpの削除ボタン 115行目付近-->
<a href='./delete.php?id=<?php echo h($id); ?>&from=item-edit'>
このパラメータでdelete.phpを書き換えていきます。
//書き換え前
if (isset($_GET['id'])) :
$id = $_GET['id'];
//修正後
if (isset($_GET['id']) && isset($_GET['from'])) :
$id = $_GET['id'];
今回はif文を更にネストするので、まずはfromパラメータの有無を判別し削除ボタンが押されているかそれ以外かの処理で分岐します。
続いて先程記載した2点の異なる処理をするための条件分岐部分です。上記の修正後コードの下に記述しています。
//index.phpの削除ボタンが押されたときの処理
//書き換え前
$sql = 'DELETE FROM records WHERE id = ?';
$stmt = $db->prepare($sql);
$stmt->bind_param('i', $id);
//書き換え後
if ($_GET['from'] === 'index') :
$backpage = $_GET['from'] . '.php?';
$sql = 'DELETE FROM records WHERE id = ?';
$stmt = $db->prepare($sql);
$stmt->bind_param('i', $id);
パラメータの値を使って条件分岐を発生させ、まずは$backpageで処理後にどのページに戻るかをセットしています。
以降のSQLに変更はありません。
続いてitem-edit.phpの削除ボタンが押されたときの処理です。プログラムの実装に移る前に、削除するのに必要なテーブル情報を取得するため、item-edit.phpの削除ボタンにさらにパラメータを追加します。
<!--115行目付近-->
<a href='./delete.php?id=<?php echo h($id); ?>&from=item-edit&table_number=<?php echo h($editItem); ?>'>
table_numberパラメータを追加しました。それではdelete.phpに削除処理を記述していきます。
index.php削除ボタン処理の下に以下を追記します。
elseif ($_GET['from'] === 'item-edit' && isset($_GET['table_number'])) :
$table_number = $_GET['table_number'];
$table_list = ['spending_category', 'income_category', 'payment_method', 'creditcard', 'qr'];
$table_name = $table_list[$table_number];
$backpage = $_GET['from'] . '.php?editItem=' . $table_number . '&';
//SQLの発行
$sql = "DELETE FROM {$table_name} WHERE id = ?";
$stmt = $db->prepare($sql);
$stmt->bind_param('i', $id);
endif;
条件文には、パラメータの値に加えて先程追加したtable_numberパラメータがセットされているかも判定に含めています。
そして処理の冒頭3行は受け取ったtable_nameパラメータの値とテーブル名の配列から$table_nameを生成し削除する選択アイテムのテーブルを準備します。
$backpageは文字列連結で「item-edit?editItem=数値&….」と出力されるようにしています。
テーブル名や戻すページをセットできたらDELETE文で削除するSQLを発行しています。
最後に$backpageを使って戻すページを書き換えていきます。
//書き換え前
header('Location: ./index.php?dataOperation=delete');
//書き換え後
header('Location: ./' . $backpage . 'dataOperation=delete');
正しい処理が行われなかった場合の戻り先も書き換えます。
//書き換え前
header('Location: ./index.php?dataOperation=error');
//書き換え後
header('Location: ./' . $backpage . 'dataOperation=error');
以上で削除プログラムが完成です。
(下記動画左:レコード削除、右:選択項目削除)
最後に
今回は選択項目を画面から更新したり削除する機能を実装しました。
次回はデータの検索機能を実装していきます。
最後までお読みいただきありがとうございました。
コメント