conserto/pomm-bundle
Symfony bundle providing a pomm service to use the Pomm Model Manager with Symfony. Configure one or more PostgreSQL connections via DSNs, enable optional logging, and access Pomm CLI commands (e.g., model generation and database browsing) through bin/console.
Install the Bundle:
composer require conserto/pomm-bundle
Configure Database Connections (config/packages/pomm.yaml):
pomm:
configuration:
default:
dsn: "pgsql://%env(DATABASE_URL)%"
pomm:default: true
.env) for credentials (e.g., DATABASE_URL=postgres://user:pass@127.0.0.1:5432/db).Generate Models via CLI:
php bin/console pomm:generate:relation-all -d src/Model -a 'App\Model' default student
StudentModel in src/Model/DefaultSchema/ with auto-generated relations.First Query in a Controller:
use App\Model\DefaultSchema\StudentModel;
public function listStudents(PommManager $pomm): Response
{
$students = $pomm['default']
->getModel(StudentModel::class)
->findAll();
return $this->render('student/list.html.twig', ['students' => $students]);
}
PommManager (auto-registered as a service) to access databases.Enable Dev Tools (Optional):
Add to config/routes/dev/pomm.yaml:
_pomm:
resource: "@PommBundle/Resources/config/routing.yml"
prefix: /_pomm
/_pomm for a database browser and query profiler.// src/Model/DefaultSchema/PostModel.php
namespace App\Model\DefaultSchema;
use PommProject\ModelManager\Model\Model;
class PostModel extends Model
{
protected $table = 'posts';
protected $jsonbColumns = ['metadata']; // JSONB column
}
$posts = $pomm['default']
->getModel(PostModel::class)
->findWhere('metadata->>\'tags\' @> $*', ['["laravel"]']);
use Symfony\Component\Serializer\SerializerInterface;
public function getPost(PostModel $post, SerializerInterface $serializer): JsonResponse
{
return new JsonResponse($serializer->serialize($post, 'json'));
}
Pattern: Use tagged services to register models/layers dynamically.
# config/services.yaml
services:
App\Model\DefaultSchema\StudentModel:
tags: ['pomm.model', { session: 'default' }]
Workflow:
pomm.model tag.PommManager into controllers/services to access any tagged model.Pattern: Use Symfony’s Value Resolver to fetch entities from request params.
use Conserto\PommBundle\ValueResolver\EntityValueResolver;
#[Route('/students/{id}')]
public function show(
#[Entity('default', modelClass: StudentModel::class)]
StudentModel $student
): Response
{
return $this->render('student/show.html.twig', ['student' => $student]);
}
Workflow:
{id} to StudentModel::find($id).modelClass attribute./students/42) without manual find() calls.Pattern: Use PommManager to coordinate transactions across databases.
public function transferFunds(
PommManager $pomm,
TransactionalInterface $transaction
): void
{
$transaction->begin($pomm['primary'], $pomm['replica']);
try {
$pomm['primary']->getModel(AccountModel::class)->debit($accountId, 100);
$pomm['replica']->getModel(LogModel::class)->log('Debit', $accountId);
$transaction->commit();
} catch (\Exception $e) {
$transaction->rollback();
}
}
Workflow:
transaction service (e.g., pomm.transactional).PommManager to services needing cross-DB transactions.Pattern: Generate models/relations from the schema.
# Generate all relations for a table
php bin/console pomm:generate:relation-all -d src/Model -a 'App\Model' default student
# Generate a single model
php bin/console pomm:generate:model -d src/Model -a 'App\Model' default post
Workflow:
post-deploy or post-migration hooks.Pattern: Extend connection pooling with custom poolers.
# config/services.yaml
services:
App\Pooler\CustomPooler:
tags: ['pomm.pooler']
arguments:
- '@pomm.connection_factory'
Workflow:
PommProject\Pomm\Connection\PoolerInterface.pomm.pooler.DSN Configuration:
DATABASE_URL (e.g., @ in passwords).%env(DATABASE_URL)% with Symfony’s .env parser or encode manually:
dsn: "pgsql://user:%24pass@host:5432/db" # $ encoded as %24
Model Namespace Mismatches:
src/Model/{DatabaseSchema}/ by default. Custom paths require:
pomm:
configuration:
default:
model_namespace: 'App\Models'
-a 'App\Models' in CLI commands to override.Symfony 6+ Deprecations:
pomm:default is deprecated in favor of session_builder: "pomm.model_manager.session_builder".config/packages/pomm.yaml:
pomm:
configuration:
default:
dsn: "pgsql://..."
session_builder: "pomm.model_manager.session_builder"
JSONB Query Syntax:
@>, ?, ->) require exact syntax. Common errors:
// Wrong: Missing quotes around JSON string
$posts->findWhere('metadata @> $*', ['{"tags": ["laravel"]}']);
// Correct: Use single quotes for JSON strings
$posts->findWhere("metadata @> $*", ["'{\"tags\": [\"laravel\"]}'"]);
jsonb_build_object() in queries for complex JSON:
$posts->findWhere('metadata @> jsonb_build_object("tags", ARRAY["laravel"])');
Value Resolver Conflicts:
NoSuitableResolverException.EntityValueResolver by ordering in config/services.yaml:
services:
Conserto\PommBundle\ValueResolver\EntityValueResolver:
tags: [controller.value_resolver, { priority: 10 }]
Enable Pomm Profiler:
config/packages/dev/pomm.yaml:
framework:
profiler:
collectors:
pomm: true
/_profiler/pomm.Log Raw Queries:
config/packages/pomm.yaml:
pomm:
logger:
service: "@monolog.logger.pomm"
var/log/pomm.log:
use Monolog\Logger;
public function __construct(Logger $pommLogger) {
$this->pommLogger = $pommLogger;
}
CLI Verbosity:
-v for debug output:
php bin/console pomm
How can I help you explore Laravel packages today?