- 配置 Laravel 使用 Supabase Postgres 資料庫涉及正確調整驅動程式、模式和環境變數。
- Supabase 為 Laravel 專門開發的驅動程式可以自動解決查詢和連線中 UUID 欄位的常見問題。
- Flysystem 轉接器可讓您將 Supabase Storage 視為另一個 Laravel 磁碟,輕鬆整合檔案上傳功能。
- 使用特權服務金鑰和配置良好的儲存桶是避免寫入錯誤和確保穩定流的關鍵。
如果你使用 Laravel 框架,並且專注於後端編程,想要遷移到像 Supabase 這樣現代化的託管式 PostgreSQL資料庫,你可能已經意識到,僅僅修改 .env 檔案中的幾個變數是不夠的。連線細節、資料庫模式、驗證和檔案儲存等問題,如果被忽略,可能會導致一些相當晦澀難懂的錯誤。
此外,如果您想更進一步,將Supabase 用作與 Laravel 磁碟系統(Storage)整合的文件存儲,事情就會變得稍微複雜一些:服務金鑰、儲存桶、端點、自訂 Flysystem 驅動程式等等。好消息是,所有東西——資料庫、儲存和 UUID 處理——都可以以相當簡潔的方式完美整合。
將 Laravel 連接到 Supabase 資料庫
第一步是建立一個可運行的 Laravel 項目,並將其連接到 Supabase 提供的 Postgres 資料庫。為此,您需要一個安裝了最新 PHP 和 Composer 的環境,您可以建立一個新專案或使用現有專案。在控制台中,只需使用標準的 Laravel 命令產生項目,然後開始設定連線即可。
專案框架建置完成後,通常的做法是安裝一個簡單的身份驗證系統。 Laravel Breeze 非常適合,因為它包含Blade 範本和基本的登入註冊流程,可以讓你快速驗證資料庫連線是否配置正確,以及是否可以順利建立使用者。
要獲取連接詳細信息,請登入您的 Supabase 控制面板並建立新的資料庫項目(您可以直接透過`database.new`建立項目,這將跳到精靈)。如果您還沒有帳戶,則會先看到註冊頁面;如果您已有帳戶,則會直接進入項目設置,您可以在其中找到連接字串。
在專案頁面的「連結」部分,您會找到一個「連線」按鈕或類似按鈕。點擊它會顯示幾種連接字串格式(URI、單一參數等)。複製完整的 URI,但請記住將密碼替換為您實際用於資料庫的密碼,因為通常會顯示預設密碼或占位符。
有了這些訊息,你需要打開 Laravel 專案的 .env 文件,更新 DB_HOST、DB_PORT、DB_DATABASE、DB_USERNAME 和 DB_PASSWORD 變數;或者,如果你希望使用完整的字串格式,則配置 DATABASE_URL 變數。這樣做的目的是確保所有配置都指向Supabase Postgres 集群,而不是你的本地主機。
在 Laravel 中設定 Postgres 驅動程式和 Supabase schema。
在 Laravel 中,資料庫配置的關鍵檔案是config/database.php。雖然可以直接使用框架自帶的 pgsql 驅動程序,但在使用 Supabase 時,通常需要應用一些額外的設置,尤其是在資料庫模式和 Postgres 特有的選項方面。
在 Laravel 中,典型的 Postgres 配置可能如下所示,位於 connections 陣列中,鍵為'pgsql' 的位置:
'pgsql' => ,
關鍵在於`search_path`參數。 Supabase 預設使用 `public` schema,也就是透過其 API 公開的 schema。如果您希望 Laravel 應用程式與該 schema 分離,避免資料表或策略衝突,強烈建議您將 `search_path` 變更為您自己的 schema,例如`laravel`,如前面的範例所示。
這樣,專案產生的遷移和表格將會建立在這個備用模式中,而不是在公共模式下。這種分離極大地簡化了從 Supabase 面板管理安全性規則、行級安全性 (RLS) 和存取權限的操作,避免覆蓋任何不應覆蓋的內容,同時保持資料庫結構的有序性。
修改完設定檔後,即可使用標準的 Laravel 指令執行遷移。這將建立身份驗證表以及您定義的任何其他表。如果一切配置正確,這些命令將自動針對Supabase Postgres 伺服器執行。
遷移完成後,使用 `artisan serve` 啟動開發伺服器,並嘗試註冊和登入使用者。如果沒有出現連線或遷移錯誤,則表示 Laravel與 Supabase 通訊正常,您可以繼續像往常一樣建立業務邏輯。
在 Laravel 中使用特定的 Supabase 驅動程式
雖然標準的 pgsql 驅動程式可以工作,但有一個軟體包為 Laravel 添加了一個 supabase 資料庫驅動程序,透過非常有用的改進擴展了 PostgreSQL 的行為,尤其是在處理 UUID 列和建立查詢的方式方面。
這個名為 prahsys/laravel-supabase 的軟體包透過 Composer 安裝,並註冊了一個名為 supabase 的額外驅動程序,您可以在 config/database.php 檔案中使用它。它內部基於 Laravel 的 Postgres 驅動程序,但整合了針對 Supabase 特定環境最佳化的設定和查詢語法。
安裝完成後,您可以在連接部分聲明類似以下內容:
'connections' => ,
// otras conexiones...
],
使用此驅動程式的優點在於,您仍然可以獲得 Postgres 引擎的全部功能,同時它還能自動處理一些 Supabase 的複雜細節,尤其是在使用UUID 作為主鍵或關係欄位時。這樣就避免了在每個複雜查詢中手動編寫類型轉換。
該軟體包的設計也與現代版本的框架和 PHP 完美契合,官方兼容Laravel 10.x、11.x 和 12.x以及 PHP 8.1 及更高版本,並且兼容任何標準 PostgreSQL 數據庫,當然也包括 Supabase。
為了確保一切正常運行,該軟體包包含一套自動化測試。您可以使用 `composer test` 命令運行測試,該命令會使用內存中的 SQLite 資料庫以提高速度;或者,您可以準備一個指向 Supabase 的 `.env.testing` 文件,然後運行 `composer test-supabase` 來在具有遠端 Postgres 的真實環境中驗證其行為。
Supabase 和 Laravel 中的 UUID 管理
Supabase 在處理 UUID 欄位時有一個特殊之處:如果嘗試直接將 UUID 與文字字串進行比較而不進行類型轉換,查詢可能會失敗或傳回意外結果。在純 Postgres 環境中,可以透過全域類型轉換或自訂運算子來解決這個問題,但 Supabase 不允許進行此類全域自訂。
這意味著可以直接查詢樣式:
SELECT *
FROM users
WHERE id = '123e4567-e89b-12d3-a456-426614174000';
它不會像你預期的那樣工作。但是,如果你進行顯式類型轉換:
SELECT *
FROM users
WHERE CAST(id AS TEXT) = '123e4567-e89b-12d3-a456-426614174000';
查詢成功。問題在於,在 Laravel 中,當你使用 Eloquent 或查詢建構器編寫查詢時,你不希望在每個 WHERE 子句中加入類型轉換。這時,前面提到的套件中的 supabase 驅動程式就派上用場了,它可以自動添加這些類型轉換。
啟用該驅動程式後,您可以執行以下常見查詢:
$user = User::find($uuidString);
$user = User::where('id', $uuidString)->first();
$users = User::whereIn('id', )->get();
不僅在直接查詢中,在連接查詢中也是如此。例如,如果您想檢索貼文並使用 UUID 欄位將其與使用者表連接起來,您可以這樣做:
$posts = Post::join('users', 'posts.user_id', '=', 'users.id')
->where('users.email', '[email protected]')
->get();
驅動程式會自動處理必要的文字類型轉換,並將其套用到相關的 UUID 欄位。這樣,你的程式碼就能保持 Laravel 的慣用風格,而無需編寫原始 SQL 或在每個複雜的查詢中使用奇怪的技巧。
如果您需要更精細地控制哪些列被視為 UUID,該軟體包為您的 Eloquent 模型提供了 ` CastsUuidColumns`特性。只需在您的模型類別中使用它,並定義一個受保護的附加列數組即可:
use Prahsys\Supabase\Traits\CastsUuidColumns;
class Post extends Model
{
use CastsUuidColumns;
protected $uuidColumns = ;
}
此特性執行三個重要操作:它將主鍵作為預設 UUID,將您聲明的任何欄位新增至`$uuidColumns`屬性,並將此資訊傳遞給查詢建構器,以便它知道在哪裡套用類型轉換。這使得所有涉及 UUID 的資料存取都保持一致且自動化。
對於更進階的場景,您可以註冊一個自訂的 UUID 列偵測器。使用該套件中的 PostgresGrammar,您可以指定一個回呼函數,該函數會根據列名或查詢上下文來判斷是否應將其視為 UUID。例如:
use Prahsys\Supabase\Database\Query\Grammars\PostgresGrammar;
PostgresGrammar::detectUuidColumnsWith(function ($columnName, $query) {
return str_contains($columnName, 'uuid_')
|| in_array($columnName, );
});
透過設定此功能,系統可以將名稱具有特定模式或位於特定清單中的所有欄位視為 UUID,從而適應您專案的特定命名約定。
在 Laravel 中整合 Supabase Storage 作為檔案系統
除了資料庫之外,許多項目還需要儲存使用者上傳的圖片、文件或其他文件。 Supabase 提供了一個基於儲存桶的儲存服務,您可以透過 Flysystem 將其用作 Laravel 的磁碟。此外,還有一個專門的適配器,可以將 Supabase Storage 作為額外的驅動程式新增至 config/filesystems.php 檔案中。
該軟體套件提供了一個 Flysystem 適配器,可與框架的儲存系統無縫整合。它符合PHP 版本 >= 8.1、Laravel 10.x 和 11.x的最低要求,並支援 PHP 檔案資訊擴充 (ext-fileinfo),Laravel 通常建議使用該擴充功能進行檔案處理。安裝使用 Composer 完成,安裝完成後,您只需在配置中定義 supabase 磁碟即可。
在config/filesystems.php檔案中,在 disks 陣列中,您需要新增類似以下內容:
'supabase' => ,
],
'signedUrlExpires' => 60 * 60 * 24,
],
`bucket` 參數通常是您在 Supabase 控制面板中建立的儲存桶的名稱(例如,`myapp-file-uploads`)。 `endpoint` 是專案儲存服務的基本 URL,也可在控制台的相應部分查看,通常由專案 URL 和區域產生。
`public` 選項指示儲存桶的內容是否預設為公開。如果為 `true`,適配器將產生無需特殊簽章的可存取 URL;如果為 `false`,則會啟用 `defaultUrlGeneration` 選項,該選項可強制產生具有 `signedUrlExpires` 指定過期時間的簽章 URL。此配置可讓您根據處理的文件類型在安全性和便利性之間取得平衡。
常規磁碟 URL 通常留空,以便適配器自動從端點推導出它。只有當您使用中間代理或 CDN,並且希望產生的路由指向該域而不是 Supabase 原生域時,才需要修改它。
排查上傳錯誤並了解 Supabase 儲存的關鍵所在
從 Laravel 上傳檔案到 Supabase Storage 時,一個相當常見的問題是收到類似「無法寫入位置 uploads/… 的檔案」的錯誤訊息。這通常表明,儘管驅動程式已配置,但由於權限不足或金鑰配置錯誤,Supabase 拒絕了寫入操作。
在 supabase 磁碟設定檔 `config/filesystems.php` 中,設定明確指定在 `key` 欄位中使用「特權金鑰」,並明確指出唯讀金鑰無效。這表示您需要使用具有儲存桶寫入權限的服務金鑰,而不能使用客戶端公共 API 金鑰或不具備修改權限的 S3 相容金鑰。
在 Supabase 面板的 API 和儲存配置部分,您會找到匿名金鑰和服務角色金鑰(或其等效項),它們具有擴充權限。您應該將此服務金鑰(而不是公用金鑰)放入 SUPABASE_SECRET_ACCESS_KEY 變數中,驅動程式隨後將使用 env('SUPABASE_SECRET_ACCESS_KEY') 讀取該變數。
如果您一直使用儲存配置中的 S3 金鑰或專案的通用 API 金鑰進行測試,則這些憑證很可能沒有對特定儲存桶的寫入權限,從而導致寫入錯誤。將密鑰值變更為具有寫入權限的有效服務密鑰,並確認儲存桶存在且名稱正確,通常可以解決此問題。
除了密碼之外,還必須驗證 SUPABASE_STORAGE_BUCKET 中定義的儲存桶是否與 Supabase 介面中建立的儲存桶完全一致(包括大小寫字母),並且端點是否對應於該儲存實例的正確 URL。諸如多一個字元或錯誤的網域名稱之類的細節都可能導致適配器無法找到檔案的實際目標位置。
使用 Laravel Breeze、Blade 和 Supabase Storage 的工作流程
資料庫和儲存配置完成後,下一步合乎邏輯的做法是將所有內容與Laravel Breeze 介面和 Blade 模板整合。這樣,使用者無需離開 Laravel 生態系統即可註冊、驗證身分並上傳檔案到 Supabase。
在控制器中,您可以使用指向 Superbase 磁碟的Storage facade。例如,要上傳從帶有文件輸入框的表單接收的文件,您可以這樣做:
if ($request->hasFile('file')) {
$path = $request->file('file')
->store('uploads', 'supabase');
}
這段程式碼指示 Laravel 使用Supabase磁碟,並將檔案放置在已配置儲存桶的虛擬上傳資料夾中。如果金鑰和端點正確,檔案將上傳到 Supabase 存儲,您可以使用標準儲存方法檢索其路徑或產生公開或簽署 URL。
這種方法的優點在於,無論應用程式使用的是本機磁碟、Amazon S3、Supabase 或其他支援的儲存服務,它都只需維護一個統一的儲存介面。切換儲存提供者只需調整 config/filesystems.php 檔案和環境變量,而不會影響業務邏輯。
透過與 Blade 和 Breeze 結合使用,您可以將上傳表單、文件清單和下載連結完全整合到應用程式的使用者體驗中。此外,Supabase Storage 基於儲存桶和策略的方法可讓您利用其存取控制和安全性規則來定義每個使用者可以查看或下載的內容。
這套完整的軟體包、驅動程式和配置生態系統使 Laravel 能夠與 Supabase 無縫協作,無論是在與 Postgres 的關係型資料方面,還是在檔案儲存和 UUID 管理方面。透過正確配置鍵、模式和驅動程序,您可以實現非常強大的集成,從而避免在未使用這些支援層的情況下手動連接這兩個平台時遇到的許多典型錯誤。
將 Laravel 與 Supabase 連接起來作為數據庫和存儲,利用專用的 Supabase 驅動程序輕鬆管理 UUID,並使用 Flysystem 適配器進行存儲,可以構建現代應用程序,其中所有復雜的基礎設施都封裝在 Laravel 簡潔的 API 之後,從遷移和身份驗證存儲桶。