mongoose-studio/phobos-framework-database-postgres
Composer 安装命令:
composer require mongoose-studio/phobos-framework-database-postgres
包简介
Phobos Framework PostgreSQL Connector for Database Layer
README 文档
README
Driver PostgreSQL para Phobos Framework Database Layer. Aprovecha las características
propias de PostgreSQL: schemas reales (search_path), INSERT ... RETURNING para leer el
id autogenerado, columnas JSONB mapeadas a arrays de PHP, y claves primarias UUIDv7
generadas en la aplicación.
Características
- 🐘 Conectividad PostgreSQL - DSN,
sslmode, y configuración de sesión - 🗂️ Schemas reales - Configuración de
search_pathy nombres calificadosschema.tabla - 🔄 Schema-per-tenant - Re-apuntado de schemas en runtime vía
SchemaRegistry - ↩️ INSERT ... RETURNING - El id autogenerado (SERIAL/IDENTITY/uuid) se lee en el INSERT
- 🧬 UUIDv7 - Claves primarias ordenadas por tiempo, generadas sin round-trip
- 📦 JSONB - Mapeo automático entre arrays de PHP y columnas JSONB vía
$casts - 🔀 Transaction Isolation - Los cuatro niveles estándar
- 🎯 Savepoints - Transacciones anidadas completas
Instalación
composer require mongoose-studio/phobos-framework-database-postgres
Dependencias
Este driver requiere:
mongoose-studio/phobos-framework^3.2mongoose-studio/phobos-framework-database^3.2- Extensión
ext-pdohabilitada - Extensión
ext-pdo_pgsqlhabilitada
Configuración
1. Registrar el Driver
En tu config/database.php:
<?php return [ 'default' => 'pgsql', 'drivers' => [ 'pgsql' => PhobosFramework\Database\Drivers\Postgres\PostgresDriver::class, ], 'connections' => [ 'pgsql' => [ 'driver' => 'pgsql', 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', 5432), 'database' => env('DB_DATABASE', 'app'), 'username' => env('DB_USERNAME', 'postgres'), 'password' => env('DB_PASSWORD', ''), 'schema' => 'public', // Opcional: search_path ], ], ];
2. Variables de Entorno
DB_HOST=127.0.0.1 DB_PORT=5432 DB_DATABASE=app DB_USERNAME=postgres DB_PASSWORD=secret
Opciones de Configuración
| Clave | Tipo | Descripción |
|---|---|---|
host |
string | Servidor PostgreSQL (requerido) |
database |
string | Nombre de la base de datos (requerido) |
port |
int | Puerto (opcional, por defecto 5432) |
username |
string | Usuario |
password |
string | Contraseña |
sslmode |
string | disable/allow/prefer/require/verify-ca/verify-full |
schema |
string | Un único schema para el search_path (ej: app) |
search_path |
string | Lista de schemas separada por comas (ej: app,public) |
timezone |
string | Zona horaria de la sesión (ej: UTC, America/Santiago) |
application_name |
string | Nombre de la aplicación (visible en pg_stat_activity) |
client_encoding |
string | Encoding del cliente (ej: UTF8) |
options |
array | Atributos PDO adicionales |
Características Específicas de PostgreSQL
Schemas y search_path
PostgreSQL organiza las tablas en schemas dentro de una misma base de datos. Hay dos formas de trabajar con ellos:
A) search_path a nivel de conexión — la entidad no declara schema y se resuelve por
el orden del search_path:
// config: 'search_path' => 'app,public' class User extends TableEntity { protected static ?string $schema = null; // resuelto por search_path protected static string $entity = 'users'; }
B) Nombre calificado por entidad — la entidad declara su schema; la capa genera
"schema"."tabla":
class Invoice extends TableEntity { protected static ?string $schema = 'ventas'; protected static string $entity = 'invoices'; // -> "ventas"."invoices" }
Schema-per-tenant (re-apuntado en runtime)
El $schema de la entidad es un alias lógico. Con SchemaRegistry puedes mapearlo a un
schema físico distinto por request, sin tocar el código de las entidades:
use PhobosFramework\Database\Schema\SchemaRegistry; // En un middleware, según el tenant del request: SchemaRegistry::getInstance()->register('ventas', "tenant_{$tenantId}"); // Ahora toda entidad con $schema = 'ventas' escribe/lee en "tenant_42"."invoices"
Claves primarias
El driver soporta tres estrategias vía $keyStrategy en la entidad:
// 1. auto (por defecto): SERIAL/IDENTITY; el id se lee con INSERT ... RETURNING class Account extends TableEntity { protected static array $pk = ['id']; protected static string $keyStrategy = 'auto'; public ?int $id = null; } // 2. uuidv7: el framework genera un UUIDv7 en PHP antes del INSERT (sin round-trip) class Document extends TableEntity { protected static array $pk = ['id']; protected static string $keyStrategy = 'uuidv7'; public mixed $id = null; // columna UUID } // 3. manual: la aplicación asigna el valor class Setting extends TableEntity { protected static array $pk = ['key']; protected static string $keyStrategy = 'manual'; public string $key = ''; }
Un PK ya asignado siempre gana: se persiste tal cual, sin generar ni releer.
JSONB y casteo de atributos
Declara $casts para mapear columnas automáticamente entre su forma en la base de datos y
su tipo nativo en PHP:
class Account extends TableEntity { protected static string $entity = 'accounts'; protected static array $casts = [ 'meta' => 'json', // JSONB <-> array PHP 'active' => 'bool', // boolean (entiende 't'/'f') 'created_at' => 'datetime', // timestamp <-> DateTimeImmutable ]; public mixed $meta = null; public mixed $active = null; } $account = new Account(); $account->meta = ['plan' => 'pro', 'seats' => 5]; $account->save(); // se persiste como JSONB $found = Account::findByPk($account->id); $found->meta['plan']; // 'pro' (array PHP)
Nota sobre operadores JSONB y placeholders: los operadores
?,?|y?&de JSONB chocan con los placeholders?de PDO. Para consultar dentro de JSONB usawhere()crudo con operadores que no colisionen (->>,@>,#>>), por ejemplo:Account::find(["meta->>'plan' = ?" => 'pro']).
DELETE ... LIMIT
PostgreSQL no soporta DELETE ... LIMIT. Si se intenta, la capa lanza una excepción clara
(LogicException) en lugar de emitir SQL inválido. Acota las filas con un WHERE.
Niveles de aislamiento
$driver->getSetIsolationLevelSQL('SERIALIZABLE'); // SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
Niveles soportados: READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE.
Tests
# Unit (sin base de datos) composer test-unit # Integración (requiere PostgreSQL real; configurar DB_* en phpunit.xml) composer test-integration # Todo composer test
Los tests de integración crean tablas y schemas temporales en la base phobos_test y los
limpian al terminar.
Arquitectura
- PostgresDriver (
src/Drivers/Postgres/PostgresDriver.php): extiendeAbstractDriver. Genera el DSN, configurasearch_path/timezone/application_name, y expone la gramática. - PostgresGrammar (
src/Drivers/Postgres/PostgresGrammar.php): extiendeAnsiGrammar(comillas dobles). ActivaRETURNINGy deshabilitaDELETE ... LIMIT.
Compatibilidad
- PostgreSQL 12+ (probado contra 18.x)
- PHP 8.4+
Licencia
Este proyecto está licenciado bajo la Licencia MIT - ver el archivo LICENSE para más detalles.
Autor
Marcel Rojas
marcelrojas16@gmail.com
Mongoose Studio
Contribuciones
Las contribuciones son bienvenidas. Por favor:
- Fork el proyecto
- Crea una rama para tu feature (
git checkout -b feature/amazing-feature) - Commit tus cambios (
git commit -m 'Add amazing feature') - Push a la rama (
git push origin feature/amazing-feature) - Abre un Pull Request
Phobos Framework by Mongoose Studio
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 5
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-07-14