Dev Study
← 解説「ルートパラメータと @Param」に戻る

サンプルコードで身につける: ルートパラメータと @Param

解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。

1:id で1件取得する

:id と @Param("id") の名前を一致させるという基本ルールだけで書ける最小例です。ID を指定した1件取得は REST API で最も頻出のエンドポイントで、この形をそのまま暗記してよいレベルの定型です。

import { Controller, Get, Param } from "@nestjs/common";

@Controller("users")
export class UsersController {
  @Get(":id") // GET /users/42 → id に "42" が入る
  findOne(@Param("id") id: string) {
    return { id, name: "Alice" };
  }
}
// :id(パス側)と "id"(取り出す側)の名前を一致させる

2固定パスは可変パスより先に書く

/users/me のような固定パスと /users/:id が共存するときの定義順を示す例です。ルートは上から順に照合されるため、可変パスを先に書くと固定パスに届かなくなる、という実務頻出のハマりどころです。

import { Controller, Get, Param } from "@nestjs/common";

@Controller("users")
export class UsersController {
  @Get("me") // 固定パスを先に定義する
  findMe() {
    return { id: "self" };
  }

  @Get(":id") // 可変パスは後ろに置く
  findOne(@Param("id") id: string) {
    return { id };
  }
}
// 逆順にすると GET /users/me も :id に吸われて
// id = "me" として findOne が動いてしまう

3パターン照合をプレーンTSで再現

@Get(":id") の裏でフレームワークが行っている「パスパターンと実際の URL の照合」をプレーン TypeScript で再現した例です。取り出した値が常に文字列になるのは URL を分割した断片だから、という理由も納得できます。

TypeScript

4@Query — クエリ文字列の受け取り

URL の ? 以降に付くクエリ文字列を受け取る @Query の例です。@Param の親戚で「URL から可変の値を取る」仲間であり、こちらも値は常に文字列で届きます。検索条件やページ番号の受け取りで毎日使います。

import { Controller, Get, Query } from "@nestjs/common";

@Controller("articles")
export class ArticlesController {
  // GET /articles/search?keyword=nest&page=2
  @Get("search")
  search(
    @Query("keyword") keyword: string,
    @Query("page") page: string,
  ) {
    // クエリ文字列も @Param と同じく常に string で届く
    return { keyword, page };
  }
}
// パスの一部なら @Param、? 以降なら @Query と使い分ける

5ネストしたリソースの実務ルーティング

「ユーザー 7 の注文一覧」のような所有関係を URL で表す、実務で定番のネストしたリソース設計です。@Controller のプレフィックス自体にもパラメータを置けることを示します。

import { Controller, Get, Param } from "@nestjs/common";

// プレフィックスにも :userId を置ける
@Controller("users/:userId/orders")
export class UserOrdersController {
  @Get() // GET /users/7/orders — ユーザー7の注文一覧
  findAll(@Param("userId") userId: string) {
    return { userId, orders: [] };
  }

  @Get(":orderId") // GET /users/7/orders/100 — 注文の詳細
  findOne(
    @Param("userId") userId: string,
    @Param("orderId") orderId: string,
  ) {
    return { userId, orderId };
  }
}