dmits/laravel-d1

Laravel integration for Cloudflare Workers services.

2.0.0 2025-11-01 02:53 UTC

This package is not auto-updated.

Last update: 2025-11-30 00:39:07 UTC


README

Latest Stable Version Total Downloads Latest Unstable Version License PHP Version Require

A seamless Laravel integration for Cloudflare D1 databases. This package allows you to use Cloudflare D1 (SQLite-compatible serverless database) with Laravel's Eloquent ORM and Query Builder, just like any other database connection.

Features

  • ๐Ÿš€ Full Laravel Integration - Use Eloquent ORM, Query Builder, and Migrations
  • ๐Ÿ”Œ PDO-Compatible - Works with Laravel's database abstraction layer
  • ๐Ÿ”’ Security-First - Built-in input validation, path traversal protection, and error sanitization
  • ๐ŸŒ Serverless Ready - Perfect for Cloudflare Workers and edge computing
  • ๐Ÿ“ฆ Easy Setup - Simple configuration and environment variables
  • โœ… Production Ready - Comprehensive security measures and testing

Requirements

  • PHP 8.1 or higher
  • Laravel 9.x or higher
  • Cloudflare account with D1 database
  • Cloudflare API token with D1 read/write permissions

Installation

Install the package via Composer:

composer require dmits/laravel-d1

The package will automatically register its service provider.

Configuration

1. Get Your Cloudflare Credentials

You'll need three pieces of information from your Cloudflare account:

  • API Token: Create one at Cloudflare API Tokens with D1 read/write permissions
  • Account ID: Found in your Cloudflare dashboard URL or sidebar
  • Database ID: The UUID of your D1 database instance

2. Configure Environment Variables

Add the following to your .env file:

CLOUDFLARE_TOKEN=your_api_token_here
CLOUDFLARE_ACCOUNT_ID=your_account_id_here
CLOUDFLARE_D1_DATABASE_ID=your_database_uuid_here

3. Add Database Connection

Update your config/database.php file to include the D1 connection:

'connections' => [
    // ... your existing connections
    
    'd1' => [
        'driver' => 'd1',
        'prefix' => '',
        'database' => env('CLOUDFLARE_D1_DATABASE_ID', ''),
        'api' => 'https://api.cloudflare.com/client/v4',
        'auth' => [
            'token' => env('CLOUDFLARE_TOKEN', ''),
            'account_id' => env('CLOUDFLARE_ACCOUNT_ID', ''),
        ],
    ],
],

4. Set Default Connection (Optional)

To use D1 as your default database connection:

'default' => env('DB_CONNECTION', 'd1'),

Or in your .env:

DB_CONNECTION=d1

Usage

Using Eloquent Models

Once configured, you can use D1 just like any Laravel database connection:

use App\Models\User;

// Create a new user
$user = User::create([
    'name' => 'John Doe',
    'email' => 'john@example.com',
]);

// Query users
$users = User::where('email', 'john@example.com')->get();

// Update
$user->update(['name' => 'Jane Doe']);

// Delete
$user->delete();

Using Query Builder

use Illuminate\Support\Facades\DB;

// Select
$users = DB::connection('d1')
    ->table('users')
    ->where('status', 'active')
    ->get();

// Insert
DB::connection('d1')->table('users')->insert([
    'name' => 'John Doe',
    'email' => 'john@example.com',
]);

// Update
DB::connection('d1')
    ->table('users')
    ->where('id', 1)
    ->update(['status' => 'inactive']);

// Raw queries
$results = DB::connection('d1')->select(
    'SELECT * FROM users WHERE created_at > ?',
    [now()->subDays(30)]
);

Using Migrations

Create migrations just like you would for any Laravel database:

php artisan make:migration create_users_table

Then in your migration:

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::connection('d1')->create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::connection('d1')->dropIfExists('users');
    }
};

Run migrations:

php artisan migrate --database=d1

Using Raw PDO (Advanced)

For advanced use cases, you can use the PDO interface directly:

use dmits\db1\D1\Pdo\D1Pdo;
use dmits\db1\CloudflareD1Connector;

$pdo = new D1Pdo(
    dsn: 'sqlite::memory:', // DSN is not used, but required for PDO
    connector: new CloudflareD1Connector(
        database: env('CLOUDFLARE_D1_DATABASE_ID'),
        token: env('CLOUDFLARE_TOKEN'),
        accountId: env('CLOUDFLARE_ACCOUNT_ID'),
        apiUrl: 'https://api.cloudflare.com/client/v4',
    ),
);

$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([1]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);

How It Works

Cloudflare D1 doesn't support direct SQL protocol connections. This package:

  1. Intercepts Laravel database queries through the d1 driver
  2. Converts queries and bindings to Cloudflare D1 API format
  3. Sends requests to Cloudflare's D1 /query endpoint
  4. Returns results in a format compatible with Laravel's database layer

All of this happens transparently - you use D1 exactly like you would MySQL, PostgreSQL, or SQLite.

Testing

This package includes a built-in test worker that simulates the Cloudflare API for local testing.

Start the Test Worker

In one terminal:

cd tests/worker
npm ci
npm run start

The worker will start on http://127.0.0.1:8787.

Run Tests

In another terminal:

# Run all tests
vendor/bin/phpunit

# Run specific test suite
vendor/bin/phpunit tests/D1Test.php

# Run security tests
vendor/bin/phpunit tests/SecurityTest.php

Testing Configuration

For testing, use these environment variables:

CLOUDFLARE_TOKEN=test
CLOUDFLARE_ACCOUNT_ID=1234
CLOUDFLARE_D1_DATABASE_ID=DB1
DB_CONNECTION=d1

And in your test configuration, point to the local worker:

'api' => 'http://127.0.0.1:8787/api/client/v4',

Security

Security is our top priority. This package implements comprehensive security measures:

  • โœ… Input Validation - All parameters are validated before use
  • โœ… Path Traversal Protection - Prevents URL manipulation attacks
  • โœ… Error Message Sanitization - Prevents information disclosure
  • โœ… HTTPS Enforcement - Secure communication in production
  • โœ… SQL Injection Prevention - Parameterized queries only

Security Best Practices

  1. Never commit credentials - Always use environment variables
  2. Use HTTPS - Only allow HTTP for localhost in development
  3. Validate input - Use Laravel's validation in your application layer
  4. Use Query Builder - Prefer Eloquent/Query Builder over raw SQL
  5. Keep updated - Regularly update dependencies

For detailed security information, see SECURITY.md.

Reporting Security Issues

Please do not create public issues for security vulnerabilities.

Instead, email d.mueller@dustiiin.de with details. We respond to security reports within 48 hours.

Limitations

  • D1 supports SQLite syntax but has some limitations compared to full SQLite
  • Transactions are supported but work differently than traditional databases
  • Some advanced SQLite features may not be available
  • Queries are executed via API, so there's network latency

Refer to Cloudflare D1 documentation for full feature details.

Troubleshooting

Connection Errors

Error: "Invalid database ID format"

  • Verify your CLOUDFLARE_D1_DATABASE_ID is a valid UUID
  • Check that the database ID exists in your Cloudflare account

Error: "Authentication failed"

  • Verify your API token has D1 read/write permissions
  • Check that your CLOUDFLARE_ACCOUNT_ID is correct
  • Ensure your token hasn't expired

Query Errors

Error: "SQL query cannot be empty"

  • Ensure you're not passing empty queries
  • Check that your migrations ran successfully

Error: "Unsupported fetch mode"

  • Currently supports PDO::FETCH_ASSOC and PDO::FETCH_OBJ
  • Use Eloquent or Query Builder for best compatibility

Performance

  • D1 queries go through the Cloudflare API, adding network latency
  • Consider caching frequently accessed data
  • Use indexes for better query performance

Contributing

We welcome contributions! Please see CONTRIBUTING.md for details.

When contributing:

  • Follow PSR-12 coding standards
  • Write tests for new features
  • Update documentation as needed
  • Ensure all tests pass before submitting

License

This package is open-sourced software licensed under the Apache-2.0 license.

Credits

Links

Made with โค๏ธ for the Laravel and Cloudflare communities