iT邦幫忙

2023 iThome 鐵人賽

DAY 24
2
影片教學

Nuxt 3 快速入門系列 第 24

[影片教學] Nuxt 3 建立部落格文章相關 API - 實戰部落格系列 Part 2

  • 分享至 

  • xImage
  •  

Yes

👆建議你可以使用影片子母畫面功能或全螢幕播放來獲得最佳的觀賞體驗,👇下方是本篇教學的相關筆記。


建立 Neon Serverless Postgres 資料庫

前往 Neon 官方網站,註冊後建立一個 Serverless Postgres 資料庫專案,使用預設的 Postgres 版本 v15,地區選擇 Asia Pacific (亞太地區)。

建立資料庫專案完成後,前往 Neon 主控台的 SQL Editor 頁面,使用下列 SQL 建立 article 文章資料表。

DROP TABLE IF EXISTS "article";

CREATE SEQUENCE IF NOT EXISTS "article_id_seq";

CREATE TABLE "public"."article" (
  "id" int4 NOT NULL DEFAULT nextval('article_id_seq'),
  "title" text,
  "content" text,
  "cover" text,
  "updated_at" timestamptz NOT NULL DEFAULT NOW(),
  PRIMARY KEY ("id")
);

回到 Neon 主控台的 Dashboard 頁面,在 Connection Details 區塊,複製資料庫的連線 URL 進行保存。

建立專案 .env 檔案與新增資料庫連線的環境變數

在實戰部落格系列的專案下,建立 .env 檔案,並在檔案內添加 DATABASE_URL 環境變數。

DATABASE_URL=""

將剛才所保存下來的 Neon Serverless Postgres 資料庫的連線 URL 添加於 DATABASE_URL 環境變數

DATABASE_URL="postgres://<USERNAME>:<PASSWORD>@<HOST>"

建立 Neon Serverless Postgres 資料庫的連線

安裝 Neon 官方提供操作資料庫的的套件

npm install -D @neondatabase/serverless

server/utils 目錄下建立一個檔案 ./server/utils/db.js

import { Pool, neonConfig } from '@neondatabase/serverless'
import ws from 'ws'
neonConfig.webSocketConstructor = ws

export const pool = new Pool({ connectionString: process.env.DATABASE_URL })

export default {
  pool
}

建立文章相關的 Server API

建立文章 API

server/api 目錄下建立一個檔案 ./server/api/articles.post.js

import { pool } from '@/server/utils/db'

export default defineEventHandler(async (event) => {
  const body = await readBody(event)

  const articleRecord = await pool
    .query('INSERT INTO "article" ("title", "content", "cover") VALUES ($1, $2, $3) RETURNING *;', [
      body.title,
      body.content,
      body.cover
    ])
    .then((result) => {
      if (result.rowCount === 1) {
        return result.rows?.[0]
      }
    })
    .catch((error) => {
      console.error(error)
      throw createError({
        statusCode: 500,
        message: '無法建立文章,請稍候再試'
      })
    })

  if (!articleRecord) {
    throw createError({
      statusCode: 400,
      message: '建立文章失敗,請稍候再試'
    })
  }

  return articleRecord
})

使用 API 測試工具 Postman 來建立文章
[POST] http://localhost:3000/api/articles

Body

{
    "title": "第 1 篇文章的標題",
    "content": "這裡寫一些文章內容",
    "cover": "https://picsum.photos/id/40/600/400"
}

建立取得指定文章 API

server/api/articles 目錄下建立一個檔案 ./server/api/articles/[id].get.js

import { pool } from '@/server/utils/db'

export default defineEventHandler(async (event) => {
  const articleId = getRouterParam(event, 'id')

  const articleRecord = await pool
    .query('SELECT * FROM "article" WHERE "id" = $1;', [articleId])
    .then((result) => result.rows?.[0])
    .catch((error) => {
      console.error(error)
      throw createError({
        statusCode: 500,
        message: '無法取得文章,請稍候再試'
      })
    })

  if (!articleRecord) {
    throw createError({
      statusCode: 400,
      message: '取得文章失敗,請稍候再試'
    })
  }

  return articleRecord
})

使用 API 測試工具 Postman 來取得指定文章
[GET] http://localhost:3000/api/articles/articleId

建立取得文章列表 API

server/api 目錄下建立一個檔案 ./server/api/articles.get.js

import { pool } from '@/server/utils/db'

export default defineEventHandler(async (event) => {
  const query = await getQuery(event)

  const page = Math.max(parseInt(query.page) || 1, 1)
  const pageSize = Math.min(Math.max(parseInt(query.pageSize) || 10, 1), 100)

  const articleRecords = await pool
    .query('SELECT * FROM "article" ORDER BY "updated_at" OFFSET $1 LIMIT $2;', [
      (page - 1) * pageSize,
      pageSize
    ])
    .then((result) => result.rows)
    .catch((error) => {
      console.error(error)
      throw createError({
        statusCode: 500,
        message: '無法取得文章列表,請稍候再試'
      })
    })

  return {
    items: articleRecords,
    page,
    pageSize
  }
})

使用 API 測試工具 Postman 來取得文章列表
[GET] http://localhost:3000/api/articles

建立刪除指定文章 API

server/api/articles 目錄下建立一個檔案 ./server/api/articles/[id].delete.js

import { pool } from '@/server/utils/db'

export default defineEventHandler(async (event) => {
  const articleId = getRouterParam(event, 'id')

  const result = await pool
    .query('DELETE FROM "article" WHERE "id" = $1;', [articleId])
    .catch((error) => {
      console.error(error)
      throw createError({
        statusCode: 500,
        message: '無法刪除文章,請稍候再試'
      })
    })

  if (result.rowCount !== 1) {
    throw createError({
      statusCode: 400,
      message: '刪除文章失敗,請稍候再試'
    })
  }

  return {
    message: '刪除文章成功'
  }
})

使用 API 測試工具 Postman 來刪除指定文章
[DELETE] http://localhost:3000/api/articles/articleId


感謝大家的閱讀,歡迎大家給予建議與討論,也請各位大大鞭小力一些:)
如果對這個 Nuxt 3 系列感興趣,可以訂閱接收通知,也歡迎分享給喜歡或正在學習 Nuxt 3 的夥伴。

範例程式碼


上一篇
[影片教學] Nuxt 3 建立第一個網站 - 實戰部落格系列 Part 1
下一篇
[影片教學] Nuxt 3 Server API 權限判斷與串接 - 實戰部落格系列 Part 3
系列文
Nuxt 3 快速入門30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
碼農
iT邦新手 4 級 ‧ 2024-01-07 21:19:51

實戰部落格系列對前端想學後端
串接資料庫和開api的人好贊~~~
恭喜系列文章能得冠軍和優選^w^
實至名歸!

話說
板主的聲音好像papaya電腦教室XD
該不會是本人~

Ryan iT邦新手 1 級 ‧ 2024-01-09 03:09:56 檢舉

感謝您的閱讀,希望有幫助到您

我只是個小小工程師,不是 PAPAYA 電腦教室的大大
/images/emoticon/emoticon01.gif

PAPAYA 電腦教室也很厲害,提供了好多實用軟體的教學

我要留言

立即登入留言