"@supabase/supabase-js": "^2.43.1"
Supabase 是個人專案「用得到的猫紋」裡,放置帳號與留言資料的地方。
一開始知道 Supabase,是因為社群誇讚以網站前端的角度,想要存取資料非常容易,在搭車時快速看過,確實覺得 CRUD 都簡化得簡單易懂。Supabase 背後的運作原理是 PostgreSQL,在加入 function 或 trigger 時,會用到不少 PostgreSQL 語法。
這篇文章不會再講一次 Supabase 文件提到的功能,而是文件上找不到參考,只好到處從社群爬文記下來的做法。
接下來的內容
使用 Auth 的帳號管理功能,要把使用者資訊複製到 public
權限的表格
如果網站或 App 使用了 Supabase 的帳號管理功能,官方文件提到:建議在每個帳號建立的當下,使用 trigger
觸發 function
,複製可以公開的資訊到 public
下的表格裡。
一開始不理解為什麼要這樣做,直到需顯示文章或留言的作者訊息。在 Supabase 裡,以 id
找出 auth
權限底下的使用者資料,必須有管理員權限。
透過 Foreign Key,存取使用者相關資訊
若使用者在網站上留言,常見要記錄的項目會有:留言內容、時間,以使用者的 UUID
。而使用者的照片和全名等資訊,則是透過使用者的 UUID
抓取資料。這可以用 insert()
寫入資料。
const nanoid = customAlphabet('1234567890abcdef', 8);
const body = await request.json();
const postId = body?.postId;
const message = body?.message;
const createdBy = body?.createdBy;
const record = {
id: nanoid(),
post_id: postId,
message,
created_by: createdBy
};
const { error } = await supabase.from('comment').insert({
...record
});
並且在 Supabase 資料庫上,把 created_by
設定 foreign key 連結至 auth.users
,如果系統找不到 UUID
,就會回傳錯誤。感覺很像設定完成了,而且系統會幫你把關資料是正確的。
問題
想要在讀取資料並且將使用者的公開資訊,例如:public.users
合併至一次的查詢,就不用一直使用 await supabase
:
const commentsQuery = supabase
.from('comments')
.select(
`id, message, created_by:users(full_name, avatar), created_at`
)
.eq('post_id', postId);
按照文件上的說明,應該可以透過 created_by
欄位的使用者 UUID
資訊,回傳 public.users
裡,對應的 full_name
和 avatar
資料。然而,這裡會出現錯誤訊息:
Could not find a relationship between 'comments' and 'users' in the schema cache
❌ 嘗試修正
既然以 foreign key 連到 auth.users
的使用者 UUID
,會找不到關連性,那連到 public.users
的使用者 UUID
呢?
得到無法設定 foreign key 的錯誤訊息:
foreign key constraint "users_id_fkey" cannot be implemented
✅ 解決方法
建立資料的時候,不要從 supabase.from('comments').insert()
填入使用者的 UUID
:
// ...
const record = {
id: nanoid(),
post_id: postId,
message
// 取消從 supabase client 填入 UUID
// created_by: createdBy
};
const { error } = await supabase.from('comment').insert({
...record
});
該欄位應要以預設值的方式填入:
接著,foreign key 就可以成功連到 public.users
的 UUID
:
import type { QueryData } from '@supabase/supabase-js';
const commentsQuery = supabase
.from('comments')
.select(
`id, message, created_by:users(id, full_name, avatar), created_at`
)
.eq('post_id', postId);
type CommentsFetchType = QueryData<typeof commentsQuery>;
const { data, error } = await asksQuery;
就會回傳該使用者的相關資料:
"data": [{
"id": "2c62b3e0",
"message": "這個商品是在哪裡找到的呢?",
"created_by": {
"id": "f211e73d-****-****-****-************",
"email": null,
"avatar": "black.svg"
},
"created_at": "2024-06-04T12:38:06.428392+00:00"
}]