Skip to content
Discord Get Started

Laravel

Laravel connects to DB9 through PHP’s PDO PostgreSQL driver and Eloquent ORM. No special adapter or driver is needed — DB9 speaks the PostgreSQL wire protocol, so Laravel’s pgsql connection works out of the box.

  • A DB9 database (create one)
  • PHP 8.1+
  • Composer
  • Laravel 10+
Terminal
db9 create --name laravel-app

Get the connection string:

Terminal
db9 db status laravel-app

Set the connection details as environment variables:

Terminal
export DB9_HOST="pg.db9.io"
export DB9_PASSWORD="YOUR_PASSWORD"

Update your .env file with the DB9 connection details:

.env
DB_CONNECTION=pgsql
DB_HOST=pg.db9.io
DB_PORT=5433
DB_DATABASE=postgres
DB_USERNAME=laravel-app.admin
DB_PASSWORD=YOUR_PASSWORD

Then update the pgsql section of config/database.php to include sslmode:

config/database.php
'pgsql' => [
'driver' => 'pgsql',
'host' => env('DB_HOST', 'pg.db9.io'),
'port' => env('DB_PORT', '5433'),
'database' => env('DB_DATABASE', 'postgres'),
'username' => env('DB_USERNAME', 'laravel-app.admin'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'prefix_indexes' => true,
'search_path' => 'public',
'sslmode' => 'require',
],

Generate a User model with a migration:

Terminal
php artisan make:model User -m

Generate a Post model with a migration:

Terminal
php artisan make:model Post -m

Edit the migration for users:

database/migrations/xxxx_xx_xx_create_users_table.php
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamps();
});
}

Edit the migration for posts:

database/migrations/xxxx_xx_xx_create_posts_table.php
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('body')->nullable();
$table->boolean('published')->default(false);
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->timestamps();
});
}

Add relationships to the models:

app/Models/User.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class User extends Model
{
protected $fillable = ['name', 'email'];
public function posts(): HasMany
{
return $this->hasMany(Post::class);
}
}
app/Models/Post.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Post extends Model
{
protected $fillable = ['title', 'body', 'published', 'user_id'];
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}
Terminal
php artisan migrate

Verify the tables exist:

Terminal
php artisan tinker
>>> \DB::select('SELECT tablename FROM pg_tables WHERE schemaname = \'public\'');

Generate a resource controller:

Terminal
php artisan make:controller UserController --resource

Add CRUD logic:

app/Http/Controllers/UserController.php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
class UserController extends Controller
{
public function index()
{
return User::all();
}
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users',
]);
$user = User::create($validated);
return response()->json($user, 201);
}
public function show(User $user)
{
return $user->load('posts');
}
public function update(Request $request, User $user)
{
$validated = $request->validate([
'name' => 'sometimes|string|max:255',
'email' => 'sometimes|email|unique:users,email,' . $user->id,
]);
$user->update($validated);
return response()->json($user);
}
public function destroy(User $user)
{
$user->delete();
return response()->noContent();
}
}

Register the routes:

routes/api.php
use App\Http\Controllers\UserController;
Route::apiResource('users', UserController::class);

Start the server and test:

Terminal
php artisan serve
curl http://localhost:8000/api/users
  • Port 5433: DB9 listens on port 5433, not the PostgreSQL default 5432.
  • TLS required: Always use sslmode=require in your database config for DB9’s hosted service.
  • Connection pooling: Set DB_CONNECTION pool size through Laravel’s database.php config or use an external pooler like PgBouncer for high-traffic apps.
  • Database name: The database is always postgres. Do not attempt to create additional databases.
  • Queue workers: If running Laravel queues with a database driver, each worker opens its own connection. Size your pool accordingly.

DB9 uses port 5433. Laravel defaults to 5432 if DB_PORT is not set. Check your .env file:

env
DB_PORT=5433

Install the PHP PostgreSQL extension. On Ubuntu/Debian:

Terminal
sudo apt install php-pgsql

On macOS with Homebrew:

Terminal
brew install php

The pdo_pgsql extension is included by default. Verify with php -m | grep pgsql.

If tables were created manually before running migrations, use the --pretend flag to check what SQL would run, then mark migrations as complete:

Terminal
php artisan migrate --pretend
php artisan migrate --path=database/migrations/xxxx_xx_xx_specific_migration.php

Confirm sslmode is set to require in your config/database.php under the pgsql connection. If you are using a DATABASE_URL environment variable, append ?sslmode=require:

env
DATABASE_URL="postgresql://laravel-app.admin:YOUR_PASSWORD@pg.db9.io:5433/postgres?sslmode=require"

Verify the username format. DB9 expects <app-name>.admin as the username (e.g., laravel-app.admin).