getCompiledSelect の罠、 useSoftDelete が抜け落ちる


体調不良で大遅刻しました・・・
申し訳ないです。

さて、

CodeIgniter4のクエリビルダにはCodeigniter3にもあった、ビルド中のクエリを取得するメソッドがある。

それが getCompiledSelect というメソッド(Codeigniter3では get_compiled_select)だが、これ、モデル中でも利用できて便利!

と思うじゃん?

実際取得してみるとあれ?となる。

app/Models/ItemModel.php
namespace App\Models;
use CodeIgniter\Model;
class ItemModel extends Model {
    protected $table = 'items';
    protected $primaryKey = 'item_no';
    protected $returnType = 'array';
    protected $useSoftDeletes = true;
    protected $allowedFields = [];
    protected $useTimestamps = false;
    protected $createdField = 'created_at';
    protected $updatedField = 'updated_at';
    protected $deletedField = 'deleted_at';
    protected $validationRules = [];
    protected $validationMessages = [];
    protected $skipValidation = false;
    protected $afterFind = [];
}
app/Contorllers/Hoge.php
$itemModel = model('ItemModel');
$itemModel->select('item_no');

echo $itemModel->getCompiledSelect(false);
// SELECT `item_no` FROM `items`

// 実行してからgetLastQueryしてみると
$itemModel->find();
echo $itemModel->getLastQuery();
// SELECT `item_no` FROM `items` WHERE `items`.`deleted_at` IS NULL

つまり、モデル中の useSoftDelete が適用されないということ。
Codeigniter3は useSoftDelete なる機能がなかった(というか、モデルとDBがFW上で紐付いていなかった)ため、論理削除のクエリもクエリビルダに含めてから get_compiled_select をするため、まず間違えることはないのだが、Codeigniter4のモデル機能に甘えてこれを忘れてしまうと 大変なことになる ので要注意。

まとめ:論理削除を用いたモデルを利用する場合は getCompiledSelect を使わずにクエリを実行してから getLastQuery をしよう(もしくは論理削除のwhere句を記述する)

※ 本当は getCompiledSelect を使わないように設計するのが一番いいのだが、そうは行かないケースは結構あるわけで・・・


解決編: getCompiledSelect で useSoftDelete が効くようにする
https://qiita.com/bananacoffee/items/1b9b56ce541174a3fb7d