1
0

初サイト制作メモ2: DB, APIを模した簡易実装をしてみる

Last updated at Posted at 2024-02-21

※備忘録用。誤った記載があるかもしれません。コメントで教えていただければ嬉しいです

DBに当たるものを直書きで用意してみる

typeは適当に定義し、それの配列としてramenListを作成

src/db/ramen.ts
export type Ramen = {
  id: string;
  name: string;
  image?: string;
  custom?: {
    volume: string;
    toppings: string;
  };
  description?: string;
};

const ramenList: Ramen[] = [
  {
    id: "1",
    name: "Shoyu Ramen",
    image: "/images/shoyu-ramen.jpg",
    description:
      "Shoyu ramen is a Japanese noodle soup that is flavored with soy sauce. It is one of the most popular and classic ramen in Japan.",
  },
  {
    id: "2",
    name: "Miso Ramen",
    image: "/images/miso-ramen.jpg",
    description:
      "Miso ramen is a Japanese noodle soup that is flavored with miso. It is one of the most popular and classic ramen in Japan.",
  },
  {
    id: "3",
    name: "Tonkotsu Ramen",
    image: "/images/tonkotsu-ramen.jpg",
    description:
      "Tonkotsu ramen is a Japanese noodle soup that is flavored with pork bone broth. It is one of the most popular and classic ramen in Japan.",
  },
];

APIを作ってみる

DBから値を取得したり値を追加したりする関数を、先ほどのファイルに追記

src/db/ramen.ts
export function getRamenList(): Ramen[] {
  return ramenList;
}

export function getRamenById(id: string): Ramen | undefined {
  return ramenList.find((ramen) => ramen.id === id);
}

export function addRamen(ramen: Ramen) {
  ramenList.push(ramen);
}

export function deleteRamen(id: string) {
  const index = ramenList.findIndex((ramen) => ramen.id === id);
  if (index !== -1) {
    ramenList.splice(index, 1);
  }
}

export function updateRamen(ramen: Ramen) {
  const index = ramenList.findIndex((r) => r.id === ramen.id);
  if (index !== -1) {
    ramenList[index] = ramen;
  }
}

先ほどの関数を、各メソッドで呼び出すよう実装。

index.tsにはデータ全てを取得したり削除したりする処理を記述。
id指定で操作したい内容は、後の[id].tsに記載。

src/pages/api/ramen/index.ts
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
//api配下のファイルは1つ1つがAPIエンドポイントとして機能する
import type { NextApiRequest, NextApiResponse } from "next";
import type { Ramen } from "@/db/ramen";
import { addRamen, getRamenList } from "@/db/ramen";

//習慣としてhandlerという名前にしている
export default function handler(
  req: NextApiRequest,
  res: NextApiResponse<Ramen[]>
) {
  if (req.method === "GET") {
    res.status(200).json(getRamenList());
  } else if (req.method === "POST") {
    const ramen = req.body as Ramen;
    addRamen(ramen);
    res.status(201).json([ramen]);
  } else {
    //一括削除の時などの処理をここに書く
    res.status(404).end();
  }
}

[id].tsでは、id指定でデータ取得・削除などできるようにする

[id].tsのファイル名にすることで、動的パラメータを持つAPIエンドポイントを作成できる。
/api/ramen/の後ろに入る値が、req.queryで取得される。

src/pages/api/ramen/[id].ts
import type { NextApiRequest, NextApiResponse } from "next";
import type { Ramen } from "@/db/ramen";
import { getRamenById, deleteRamen, updateRamen } from "@/db/ramen";

export default function handler(
  req: NextApiRequest,
  res: NextApiResponse<Ramen | undefined>
) {
  const { id } = req.query;
  if (!id || Array.isArray(id) || id.length === 0) {
    res.status(400).end();
    return;
  }
  if (req.method === "GET") {
    const ramen = getRamenById(id);
    if (ramen) {
      res.status(200).json(ramen);
    } else {
      res.status(404).end();
    }
  } else if (req.method === "PUT") {
    const ramen = req.body as Ramen;
    if (ramen.id !== id) {
      res.status(400).end();
      return;
    }
    updateRamen(ramen);
    res.status(200).json(ramen);
  } else if (req.method === "DELETE") {
    deleteRamen(id);
    res.status(204).end();
  } else {
    res.status(404).end();
  }
}

※importで@を使うためには、以下のようにエイリアスを設定しておく。

tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
  "exclude": ["node_modules"]
}

APIを叩いてみる

GETは、単にブラウザのURLに入れればOK
GET api/ramen
http://localhost:8888/api/ramen
※3000番は他で使っているため、package.json"dev": "next dev -p 8888"と設定してある
http://localhost:8888/api/ramen で開いたときにhandler内のGETメソッドが実行されるのは、Next.jsのAPIルート機能によるもの。exportされている関数を実行する。Next.jsでは、pages/apiディレクトリ内に配置されたファイルは、サーバー側で実行されるAPIエンドポイントとして扱われる

スクリーンショット 2024-02-21 22.11.13.png

他のメソッドは、Postmanで試す。
スクリーンショット 2024-02-21 22.16.59.png
スクリーンショット 2024-02-21 22.17.13.png

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0