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.
Prerequisites
Section titled “Prerequisites”- A DB9 database (create one)
- PHP 8.1+
- Composer
- Laravel 10+
Create a DB9 Database
Section titled “Create a DB9 Database”db9 create --name laravel-appGet the connection string:
db9 db status laravel-appSet the connection details as environment variables:
export DB9_HOST="pg.db9.io"export DB9_PASSWORD="YOUR_PASSWORD"Configure Database Connection
Section titled “Configure Database Connection”Update your .env file with the DB9 connection details:
DB_CONNECTION=pgsqlDB_HOST=pg.db9.ioDB_PORT=5433DB_DATABASE=postgresDB_USERNAME=laravel-app.adminDB_PASSWORD=YOUR_PASSWORDThen update the pgsql section of config/database.php to include sslmode:
'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',],Define Models
Section titled “Define Models”Generate a User model with a migration:
php artisan make:model User -mGenerate a Post model with a migration:
php artisan make:model Post -mEdit the migration for users:
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:
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:
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); }}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); }}Run Migrations
Section titled “Run Migrations”php artisan migrateVerify the tables exist:
php artisan tinker>>> \DB::select('SELECT tablename FROM pg_tables WHERE schemaname = \'public\'');Controllers and Routes
Section titled “Controllers and Routes”Generate a resource controller:
php artisan make:controller UserController --resourceAdd CRUD logic:
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:
use App\Http\Controllers\UserController;
Route::apiResource('users', UserController::class);Start the server and test:
php artisan servecurl http://localhost:8000/api/usersProduction Notes
Section titled “Production Notes”- Port 5433: DB9 listens on port
5433, not the PostgreSQL default5432. - TLS required: Always use
sslmode=requirein your database config for DB9’s hosted service. - Connection pooling: Set
DB_CONNECTIONpool size through Laravel’sdatabase.phpconfig 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.
Troubleshooting
Section titled “Troubleshooting”Connection refused on port 5432
Section titled “Connection refused on port 5432”DB9 uses port 5433. Laravel defaults to 5432 if DB_PORT is not set. Check your .env file:
DB_PORT=5433PDO pgsql extension not found
Section titled “PDO pgsql extension not found”Install the PHP PostgreSQL extension. On Ubuntu/Debian:
sudo apt install php-pgsqlOn macOS with Homebrew:
brew install phpThe pdo_pgsql extension is included by default. Verify with php -m | grep pgsql.
Migration errors: relation already exists
Section titled “Migration errors: relation already exists”If tables were created manually before running migrations, use the --pretend flag to check what SQL would run, then mark migrations as complete:
php artisan migrate --pretendphp artisan migrate --path=database/migrations/xxxx_xx_xx_specific_migration.phpSSL connection errors
Section titled “SSL connection errors”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:
DATABASE_URL="postgresql://laravel-app.admin:YOUR_PASSWORD@pg.db9.io:5433/postgres?sslmode=require"Authentication failed
Section titled “Authentication failed”Verify the username format. DB9 expects <app-name>.admin as the username (e.g., laravel-app.admin).
Next Pages
Section titled “Next Pages”- Connect — connection strings and authentication
- Production Checklist — deployment readiness