如何将 Supabase 与 Laravel 集成以实现数据库和存储

最后更新: 12月5 2025
  • 配置 Laravel 使用 Supabase Postgres 数据库涉及正确调整驱动程序、模式和环境变量。
  • Supabase 为 Laravel 专门开发的驱动程序可以自动解决查询和连接中 UUID 列的常见问题。
  • Flysystem 适配器允许您将 Supabase Storage 视为另一个 Laravel 磁盘,轻松集成文件上传功能。
  • 使用特权服务密钥和配置良好的存储桶是避免写入错误和确保稳定流的关键。

适用于 Laravel 的 Supabase

如果你使用 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 或在每个复杂的查询中使用奇怪的技巧。

  Python 和数据库:终极初学者指南

如果您需要更精细地控制哪些列被视为 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') 读取该变量。

  API主动防御和漏洞扫描器

如果您一直使用存储配置中的 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 之后,从迁移和身份验证到将文件上传到安全存储桶。

Laravel 中的 Blade 堆栈指令
相关文章:
Laravel 中的 Blade 指令 hasStack 和高级堆栈控制