Codeigniter 4 におけるdeleted_atの挙動について

この記事は2025/08/01に作成されました。
データベースにおける「削除」の概念ですが、完全にデータを削除する物理削除と特定のフラグを立てるなどして「このデータは削除されている」と扱う論理削除が存在します。
Codeigniter 4では、deleted_atというカラムに削除した時間を格納することで、「ここがNULLでなければ削除したものとして扱う」という形に自動的にしてくれるシステムが存在します。
システムの有効化
Codeigniter 4ではテーブルごとにModelを作成しますが、そのModel内で以下のコードを記載するとそのmodelを経由した時のみ論理削除がONになります。
protected $useSoftDeletes = true;
なお「modelを経由した時のみ」ですので、例えば$db->queryを使用するなど、SQL文を直接記載した場合はこの設定が読まれる事はないためそのまま物理削除が行われてしまいます。
挙動の変化について
$useSoftDeletesをtrueにすると以下の挙動が変化します。
◆delete()を指定した時の挙動が変化する
●$UsersModel->delete(1); を行った場合
//通常時(usersテーブルのid:1のデータを削除しようとした場合)
DELETE FROM users WHERE id = 1
//useSoftDeletes有効時(条件は上と同じ)
UPDATE users SET deleted_at = '(現在時刻)' WHERE id = 1
◆find(),first(),findAll()などのデータ取得系の挙動が変化する。
●$UsersModel->findAll(); を行った場合
//通常時
SELECT * FROM users
//useSoftDeletes有効時
//deleted_atがNULLであるデータを取得する、というSQL文が追加される
SELECT * FROM users WHERE "users"."deleted_at" IS NULL
論理削除をONにした環境で、データの物理削除を行いたい
何らかの理由でデータの物理削除を行いたい場合は、delete文の第2引数にtrueを付与するだけで削除できます。
●$UsersModel->delete(1,true)
削除済みデータを取り扱う
以上の自動的に行われるSQL補完により、削除されたデータが取得されることは自動的になくなります。
逆に言えばdeleted_atに値が入っているデータを取得できなくなってしまうのですが、それを回避するための「withDeleted()」「onlyDeleted()」という命令があります。
●$UserModel->withDeleted()->findAll();
//自動で付与されているdeleted_atの条件が外れ、全データが取得される
SELECT * FROM users
●$UserModel->onlyDeleted()->findAll();
//逆に「削除されているデータのみ」を取得することができる。
SELECT * FROM users WHERE "users"."deleted_at" IS NOT NULL
updateの落とし穴について
update()命令に関しては、deleted_atを判定するためのSQL文は追加されないため、論理削除されているデータでもデータの更新ができてしまいます。
●$UsersModel->update(1,array('status'=>'1'));
UPDATE users SET status= '1' WHERE users.id IN (1)
上記のように削除データに対してID指定をする場面はまず無いでしょうが、特定の値を持つデータ郡に対して一括置換などを行いたい時など、問題が発生するおそれがあります。
そのため、一括置換を行いたい場合は手動でdeleted_atがNULLであることを確認したほうがいいでしょう。
●$UsersModel->where('type','1')->set('status','1')->update(1);
//これで実行すると論理削除データも含まれてしまう
UPDATE users SET status= '1' WHERE type = '1'
●$UsersModel->where('type','1')->where('deleted_at',NULL)->set('status','1')->update(1);
//このようにdeleted_atがNULLであることをチェックすることで回避できる
UPDATE users SET status= '1' WHERE type = '1'AND deleted_at IS NULL
逆に言えば、IDを指定してupdateでNULLを指定すればそれだけでデータの復旧も可能です。
まとめ
Codeigniter 4には論理削除をサポートするシステムが存在しますが、updateの方ではサポートされていないというちょっとした落とし穴もありますので、ご注意ください。
プログラマー / S.Y
PHPフレームワーク「CodeIgniter」を用いたWebサイト開発を専門とする。要件に応じ、WordPressサイトの構築から、JavaScriptを活用した動的なフロントエンド・バックエンドの実装まで、幅広く担当する。