コンテンツにスキップ
Sutando
Esc
↑↓移動↵開く⌘Jプレビュー

Sutando のモデルリレーション:hasMany、belongsTo とそれ以降

モデルリレーションは ORM の最も強力な機能の一つです。Sutando では、Laravel Eloquent ライクな直感的な API でリレーションを定義・操作できます。

モデルリレーションは ORM の最も強力な機能の一つです。Sutando では、Laravel Eloquent ライクな直感的な API でリレーションを定義・操作できます。

リレーションタイプ

Sutando は以下のリレーションタイプをサポートしています:

  • hasOne — 1対1
  • hasMany — 1対多
  • belongsTo — 多対1(逆方向)
  • belongsToMany — 多対多

1対多(hasMany / belongsTo)

最も一般的なリレーションです。ユーザーが複数の投稿を持つ例:

import { Model } from 'sutando';

class User extends Model {
  table = 'users';
  relationPosts() {
    return this.hasMany(Post, 'user_id');
  }
}

class Post extends Model {
  table = 'posts';
  relationUser() {
    return this.belongsTo(User, 'user_id');
  }
}

使用例

// ユーザーの投稿を取得
const user = await User.query().find(1);
const posts = await user.getRelated('posts');

// リレーション経由で作成
const post = await user.related('posts').create({
  title: '新しい投稿',
  content: '内容',
});

// 投稿からユーザーを取得
const post = await Post.query().find(1);
const author = await post.getRelated('user');

1対1(hasOne)

class User extends Model {
  table = 'users';
  relationProfile() {
    return this.hasOne(Profile, 'user_id');
  }
}

// 使用例
const user = await User.query().find(1);
const profile = await user.getRelated('profile');

多対多(belongsToMany)

ユーザーとロールの例:

class User extends Model {
  table = 'users';
  relationRoles() {
    return this.belongsToMany(Role, 'role_user', 'user_id', 'role_id');
  }
}

class Role extends Model {
  table = 'roles';
  relationUsers() {
    return this.belongsToMany(User, 'role_user', 'role_id', 'user_id');
  }
}

使用例

// ユーザーのロールを取得
const user = await User.query().find(1);
const roles = await user.getRelated('roles');

// ロールを付与
await user.related('roles').attach([1, 2, 3]);

// ロールを解除
await user.related('roles').detach([2]);

// ロールを同期(不要なものは削除)
await user.related('roles').sync([1, 3]);

事前読み込み(Eager Loading)

N+1 問題を回避するために、事前読み込みを使います:

// N+1 問題(非推奨)
const users = await User.query().get();
for (const user of users) {
  const posts = await user.getRelated('posts'); // 各ユーザーごとにクエリが実行される
}

// 事前読み込み(推奨)
const users = await User.query().with('posts').get();
// 合計2クエリ:ユーザー1回 + 投稿1回

// ネストされた事前読み込み
const users = await User.query()
  .with('posts.comments.user')
  .get();

遅延読み込み(Lazy Loading)

const user = await User.query().find(1);
const posts = await user.getRelated('posts'); // ここでクエリが実行される

条件付きリレーション

// 公開済みの投稿のみを事前読み込み
const users = await User.query()
  .with({
    posts: query => query.where('published', true)
  })
  .get();

リレーションのカウント

// 投稿数と一緒にユーザーを取得
const users = await User.query()
  .withCount('posts')
  .get();

console.log(users.get(0).posts_count);

まとめ

Sutando のリレーション API は、Laravel Eloquent の直感的な設計を引き継いでいます。宣言的なメソッドでリレーションを定義し、事前読み込みでパフォーマンスを最適化できます。

ドキュメント でさらに詳しく。

このページは役に立ちましたか?