How To Integrate Supabase With Laravel For Simple Crud Step By Step Guide

image
image
image
image
image
image
image
image
How to Integrate Supabase with Laravel for Simple CRUD (Step-by-Step Guide)

How to Integrate Supabase with Laravel for Simple CRUD (Step-by-Step Guide)

Before Jumping into the supabse, you need keys and URL to create a account on supabase click here - https://supabase.com/dashboard/sign-in?returnTo=%2Forg

After creating you need to collect your key and URL from the dashboard, see the below URL

and for the crud example I have created a table named as product here, see the below image on how to creating tables in supabase, while creating the table, please create columns as well.

If you're building a Laravel API and want to leverage Supabase for your backend storage, this guide is for you! Supabase is an open-source Firebase alternative that provides a real-time PostgreSQL database and RESTful API, making it a perfect backend-as-a-service (BaaS) for Laravel apps.

In this tutorial, we’ll walk through how to perform CRUD (Create, Read, Update, Delete) operations using Supabase directly in a Laravel controller—no services, no packages, just native HTTP calls.

🚀 Why Use Supabase with Laravel?

  1. PostgreSQL-powered: Full SQL capability with powerful Supabase REST API
  2. Scalable backend: Perfect for APIs, SaaS apps, and admin panels
  3. Real-time updates: Stream changes directly to the frontend
  4. Authentication and storage: Optional extras built-in

🧱 Step 1: Set Up Your Laravel Project

First, make sure you have Laravel 10 or newer installed.

composer create-project laravel/laravel laravel-supabase
cd laravel-supabase

🔐 Step 2: Get Your Supabase Credentials

  1. Go to https://app.supabase.com and create a project.
  2. Go to Project Settings → API and copy:
  3. SUPABASE_URL
  4. SUPABASE_ANON_KEY
  5. Create a table named products with columns like id, name, price.

📝 Step 3: Update Your .env File

SUPABASE_URL=https://your-project-id.supabase.co
SUPABASE_API_KEY=your-anon-key
SUPABASE_TABLE=products

Also, update config/services.php:

'supabase' => [
'url' => env('SUPABASE_URL'),
'api_key' => env('SUPABASE_API_KEY'),
'table' => env('SUPABASE_TABLE'),
],

🛠 Step 4: Create the ProductController

Run:

php artisan make:controller ProductController

Paste the following code inside app/Http/Controllers/ProductController.php:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;

class ProductController extends Controller
{
protected $baseUrl;
protected $apiKey;
protected $table;

public function __construct()
{
$this->baseUrl = env('SUPABASE_URL');
$this->apiKey = env('SUPABASE_API_KEY');
$this->table = env('SUPABASE_TABLE');
}

protected function headers()
{
return [
'apikey' => $this->apiKey,
'Authorization' => 'Bearer ' . $this->apiKey,
'Content-Type' => 'application/json',
'Accept' => 'application/json',
];
}

public function index()
{
$response = Http::withHeaders($this->headers())
->get("{$this->baseUrl}/rest/v1/{$this->table}");

return response()->json($response->json(), $response->status());
}

public function store(Request $request)
{
$data = $request->validate([
'name' => 'required|string',
'price' => 'required|numeric',
]);

$response = Http::withHeaders($this->headers())
->post("{$this->baseUrl}/rest/v1/{$this->table}", $data);

return response()->json($response->json(), $response->status());
}

public function show($id)
{
$response = Http::withHeaders($this->headers())
->get("{$this->baseUrl}/rest/v1/{$this->table}?id=eq.{$id}");

return response()->json($response->json(), $response->status());
}

public function update(Request $request, $id)
{
$data = $request->only(['name', 'price']);

$response = Http::withHeaders($this->headers())
->patch("{$this->baseUrl}/rest/v1/{$this->table}?id=eq.{$id}", $data);

return response()->json($response->json(), $response->status());
}

public function destroy($id)
{
$response = Http::withHeaders($this->headers())
->delete("{$this->baseUrl}/rest/v1/{$this->table}?id=eq.{$id}");

return response()->json(['message' => 'Deleted'], $response->status());
}
}

🔗 Step 5: Define API Routes

Edit your routes/api.php file:

use App\Http\Controllers\ProductController;

Route::get('/products', [ProductController::class, 'index']);
Route::post('/products', [ProductController::class, 'store']);
Route::get('/products/{id}', [ProductController::class, 'show']);
Route::put('/products/{id}', [ProductController::class, 'update']);
Route::delete('/products/{id}', [ProductController::class, 'destroy']);

📦 Step 6: Enable Supabase Table Access

To test in development, go to Table Editor → Policies in Supabase and create this policy:

-- Read and write access for everyone
CREATE POLICY "Allow full access"
ON public.products
FOR ALL
USING (true);
Warning: Never use true in production unless you have proper auth set up.

you can simply enable or disable the RLS from the sidebar, see the below image

🧪 Example API Requests

Create a Product

curl -X POST http://localhost:8000/api/products \
-H "Content-Type: application/json" \
-d '{"name":"Laptop","price":79999}'

Get All Products

curl http://localhost:8000/api/products

Get Single Product

curl http://localhost:8000/api/products/1

Update Product

curl -X PUT http://localhost:8000/api/products/1 \
-H "Content-Type: application/json" \
-d '{"name":"Gaming Laptop","price":99999}'

Delete Product

curl -X DELETE http://localhost:8000/api/products/1

🧠 Bonus Tips

  1. ✅ Use Laravel validation for data consistency
  2. 🔒 Secure your API with Laravel Sanctum or Passport
  3. 🔁 Use eq., like., and ilike. for filtering
  4. 🧩 Add pagination via query params like limit and offset

📌 Conclusion

You’ve now fully integrated Supabase with Laravel using just a controller — no SDKs or external packages required. This setup is clean, fast, and perfect for any Laravel-based API that needs a managed PostgreSQL backend with Supabase.

Download The Project From Github

https://github.com/codehunger-team/supabase-integration-with-laravel.git