今回は削除処理の追加とSQL実行時にトランザクションを使用するように修正します。
複数件の更新や削除がある場合は、トランザクションは実務ではほぼ必須なので使えるようにしておきましょう。
(基本的な使い方を覚えれば簡単です。)
実装する流れ
削除処理を実装するための流れです。
- 一覧画面からidを選択して更新画面に遷移
- 更新画面に削除ボタンを追加する
- 削除ボタン押下時、DBから削除
- その後、一覧画面に遷移
削除処理の実装
更新画面に削除ボタンを追加する
save.php(ビュー)に削除ボタンを作成します。
aタグを使用したリンク(GET送信)でも作れますが、今回は実務でもよくつかわれるPOST送信を使用します。
aタグだと、引数(今回でいうとid)が画面で簡単に(リンクで)確認できてしまうが望ましくないことからPOSTを使用します。
<body>
<h1>新規登録・更新</h1>
<form action="/test/save" method="POST">
<?= csrf_field() ?>
<input type="hidden" name="id" value="<?= $formObj["id"] ?>">
<div>
ユーザ名<input type="text" name="user_nm" value="<?= $formObj["user_nm"] ?>">
</div>
<br>
<div>
年齢<input type="text" name="age" value="<?= $formObj["age"] ?>">
</div>
<input type="submit" value="更新">
</form>
<?php //↓追加 ?>
<?php if($formObj["id"] != ''): ?>
<form action="/test/delete" method="POST">
<?= csrf_field() ?>
<input type="hidden" name="id" value="<?= $formObj["id"] ?>">
<input type="submit" value="削除">
</form>
<?php endif; ?>
<?php //↑追加 ?>
</body>
ルートを追加
Route.phpに追加します。
<?php
use CodeIgniter\Router\RouteCollection;
/**
* @var RouteCollection $routes
*/
$routes->get('/', 'Home::index');
$routes->get('/test', 'TestController::index');
$routes->get('/test/detail', 'TestController::detail');
$routes->get('/test/detail/(:num)', 'TestController::detail/$1');
$routes->post('/test/save', 'TestController::save');
$routes->post('/test/delete', 'TestController::delete'); //←追加メソッドはpostなので注意
コントローラ追加
/**
* 削除
*/
public function delete()
{
//postされた値を取得
$formObj = $this->request->getPost();
$params = [];
$sql = "";
$sql .= " DELETE FROM ";
$sql .= " ac_m_user ";
$sql .= " WHERE ";
$sql .= " id = ? "; $params[] = $formObj["id"];
$query = $this->db->query($sql, $params);
return redirect()->to('/test');
}理屈は前回紹介した登録、更新系と同じなので説明は省きます。
後ほど、この削除処理と登録・更新処理にトランザクション処理を追加します。



上記の例ではid「4」の人を指定し、削除しています。
トランザクションの実装
トランザクションとは簡単に言うと
一覧の処理をまとめて、成功すれば全部実行。失敗したら全部なかったことにする仕組みです。
例として3件のデータ(なんでもいい)を一気に登録するとします。
一件目成功、二件目何らかの理由で失敗、三件目成功のパターンでトランザクションを使用していなかった場合、どうなると思いますか?
一件目と三件目だけ登録されます。データが中途半端になってしまいますよね。
そこでトランザクションを使用するとすべてなかったことにしてくれるんです。
すべてが成功した場合→まとめて確定(commit)
途中で一つでも失敗→全部元に戻す(rollback)
という動きになります。
そしてもう一つ登場するのがtry catch
これは例外エラー(予期せぬエラー)が発生したときにそのエラーをキャッチして別の処理を流すことができます。
tryのなかでSQLを実行し何もなければそのままコミット。エラーが発生すればcatchの中に自動的に入ってrollbackするという安全な流れを作ることができます。
コントローラの修正
saveメソッドは以下のように修正
/**
* 登録・更新
*/
public function save()
{
//postされた値を取得
$formObj = $this->request->getPost();
try {
//トランザクション開始
$this->db->transBegin();
$params = [];
$sql = "";
if ($formObj["id"] == '') {
//idがない場合は登録とする
$sql .= " INSERT INTO ac_m_user ( ";
$sql .= " user_nm ";
$sql .= " ,age ";
$sql .= " ) VALUES ( ";
$sql .= " ? "; $params[] = $formObj["user_nm"];
$sql .= " ,? "; $params[] = $formObj["age"];
$sql .= " ) ";
} else {
//それ以外は更新
$sql .= " UPDATE ac_m_user SET ";
$sql .= " user_nm = ? "; $params[] = $formObj["user_nm"];
$sql .= " ,age = ? "; $params[] = $formObj["age"];
$sql .= " WHERE ";
$sql .= " id = ? "; $params[] = $formObj["id"];
}
$query = $this->db->query($sql, $params);
//コミット
$this->db->transCommit();
return redirect()->to('/test');
} catch (\Exception $e) {
log_message('error', $e->getMessage());
//ロールバック
$this->db->transRollback();
//エラーが面に戻したり。。
// return redirect()->to('xxxx');
}
}deleteメソッドの修正
/**
* 削除
*/
public function delete()
{
//postされた値を取得
$formObj = $this->request->getPost();
try {
//トランザクション開始
$this->db->transBegin();
$params = [];
$sql = "";
$sql .= " DELETE FROM ";
$sql .= " ac_m_user ";
$sql .= " WHERE ";
$sql .= " id = ? "; $params[] = $formObj["id"];
$query = $this->db->query($sql, $params);
//コミット
$this->db->transCommit();
return redirect()->to('/test');
} catch (\Exception $e) {
log_message('error', $e->getMessage());
//ロールバック
$this->db->transRollback();
//エラーが面に戻したり。。
// return redirect()->to('xxxx');
}
}まとめ
いかがでしたでしょうか。
ちょっとトランザクションとtry catchについては説明が長くなってしまいましたが、この組み合わせを使用するとプログラムをより安全に実行することができます。
「トランザクション」
途中でエラーが起きてもなかったことにできる
「try catch」
プログラムの突然のエラーでも安全に処理できる
両方組み合わせると予期せぬエラーが起きてもデータが壊れない、安心安全な処理が作れる
実務だとこの例外エラー時の処理は必須かつ、この条件のときにはエラーとしてロールバックなんてこともありますので基礎的な部分だけでも覚えておきましょう。
