Sutando のソフトデリート、フック、スコープ
Sutando の強力な機能であるソフトデリート、モデルイベント(フック)、クエリスコープについて解説します。
Sutando の強力な機能であるソフトデリート、モデルイベント(フック)、クエリスコープについて解説します。
ソフトデリート
ソフトデリートは、レコードを実際に削除するのではなく、deleted_at カラムに日付を設定して論理削除を行う機能です。
設定
import { Model, compose, SoftDeletes } from 'sutando';
class Post extends compose(Model, SoftDeletes) {
table = 'posts';
}
使用例
// ソフトデリート
const post = await Post.query().find(1);
await post.delete(); // deleted_at に日付が設定される
// ソフトデリートされたレコードも含めて取得
const allPosts = await Post.query().withTrashed().get();
// ソフトデリートされたレコードのみ取得
const trashedPosts = await Post.query().onlyTrashed().get();
// 復元
const trashedPost = await Post.query().onlyTrashed().find(1);
await trashedPost.restore();
// 完全に削除
await post.forceDelete();
モデルイベント(フック)
モデルのライフサイクルイベントにフックして、カスタムロジックを実行できます。
利用可能なイベント
creating— 作成前created— 作成後updating— 更新前updated— 更新後saving— 保存前(作成・更新共通)saved— 保存後deleting— 削除前deleted— 削除後
使用例
// スラグの自動生成
Post.creating(async (post) => {
post.slug = post.title.toLowerCase().replace(/\s+/g, '-');
});
// 更新日時の記録
Post.updating(async (post) => {
post.updated_at = new Date();
});
// 削除時のログ記録
Post.deleting(async (post) => {
console.log(`記事を削除: ${post.title}`);
});
クエリスコープ
クエリスコープを使うと、再利用可能なクエリ条件を定義できます。
ローカルスコープ
class Post extends Model {
table = 'posts';
scopePublished(query) {
return query.where('published', true);
}
scopeRecent(query) {
return query.orderBy('created_at', 'desc');
}
scopeByUser(query, userId) {
return query.where('user_id', userId);
}
}
// 使用例
const posts = await Post.query().published().recent().get();
const userPosts = await Post.query().byUser(1).published().get();
グローバルスコープ
import { Model, Scope } from 'sutando';
class PublishedScope extends Scope {
apply(builder, model) {
builder.where('published', true);
}
}
class Post extends Model {
table = 'posts';
static booted() {
super.booted();
this.addGlobalScope('published', new PublishedScope());
}
}
// すべてのクエリに published = true が自動的に適用される
const posts = await Post.query().get();
まとめ
ソフトデリート、フック、クエリスコープを組み合わせることで、データ整合性を保ちながら開発効率を大幅に向上できます。これらの機能は Laravel Eloquent から直接インスピレーションを得ており、直感的に使えます。
ドキュメント でさらに詳しく。