← FC Coder · HomePhase 03 · Lesson 36 · 60 min
Lesson36
Phase Three · Fullstack · Matchday 36 · Link The Tables

多用户阵容
外键关联 + 用户隔离

Today's 3 Jobs · 今天这三件事
  1. 01
    squads 加 userId 外键 · push
    .references
  2. 02
    createSquad 注入 currentUser.id
    登录才能建
  3. 03
    🌟 /profile/[name] · 列该用户全部阵容
    .where userId

foreign key (`squads.userId.references(users.id)`) 把阵容和用户串起来。createSquad 注入 currentUser · /profile/[name] 用 .where 过滤。三抽屉关联 baby:players / squads / users 通过 id 串。下节课加 public/private。

Concept · 三抽屉关联

players + squads + users 通过 id 串

Chalk Board · 关联
squads.userId ──refs──► users.id
FK
.references(() => users.id)
.where(eq(squads.userId, user.id))
好处
数据不重 · 一处改处处对

这是 1NF baby。Phase 5 进阶会讲 join / index / normalization。

Half 2 · 在屏幕上

FK · createSquad · /profile · AI 权限

01外键 + 旧数据处理
01Min

Cursor + pnpm dev

老三件套。
02Min

squads schema 加 userId: integer().notNull().references(() => users.id)

外键。
03Min

清空旧 squads(无 userId)· drizzle-kit push

如果有旧数据 · studio 清空 squads 表 · 再 push。否则 push 失败。
02action + profile 页
04Min

createSquad 内拿 getCurrentUser() · userId: user.id

auth.ts getCurrentUser · 注入。未登录 throw。
05Min

新建 app/profile/[name]/page.tsx · 列该用户全部阵容

查 user by name · 再查 squads where userId=user.id · 渲染链接列表。
03AI deleteSquad 权限
06Min

登 '哈兰德' · 创建 2 个阵容 · 访问 /profile/哈兰德

看 2 个 link。
07Min

隐身窗 登 '福登' · 创 1 个 · 访问 /profile/福登

看 1 个 link · 不看到哈兰德的(.where 过滤)。
08Min

AI Supervised:加 deleteSquad · 检查 squad.userId === currentUser.id 才删

Cmd+K · '加权限检查 · 别人不能删你的'。父亲必看(高风险)。
09Min

📸 截图两个 /profile 页

Phase 3 第十一张战利品。
讲给爸爸听

4 题 · 关联表

01foreign key 是什么?Hint ↓

一列的值必须存在另一表里。squad.userId 必须真有这个用户。

02数据库标准化 baby?Hint ↓

不要在两处存同一份数据。一处改 · 处处对。1NF baby。

03/profile/哈兰德 vs /profile/福登 不同?Hint ↓

.where(eq(squads.userId, user.id)) 过滤。

04本课为什么还不限制看别人?Hint ↓

public/private 是下节课。今天先关联。

温度计

给「串抽屉」打分

今天难度Difficulty
0
今天开心Fun
0
Final Whistle · 终场哨

抽屉串起来 —— 阵容知道是谁的。

还有 9 步没打勾。Step 7 两个 profile 看到各自的 = 算过。