conserto/pomm-model-manager
Pomm ModelManager adds a lightweight model layer for PostgreSQL in Pomm: built-in CRUD plus count/exists, flexible entities, embedded entity conversion, and transactional model computations with advanced Postgres transaction settings. Not an ORM.
Installation
composer require conserto/pomm-model-manager
Requires pomm-project/pomm (≥v4.0) and PHP ≥8.1.
Basic Configuration
Define a Pomm connection in config/database.php:
'pomm' => [
'default' => [
'dsn' => 'pgsql:host=localhost;dbname=test',
'user' => 'user',
'password' => 'pass',
],
],
First Model
Extend Conserto\PommModelManager\ModelManager and define a table:
use Conserto\PommModelManager\ModelManager;
use PommProject\Pomm\Adapter\PostgreSql\PostgreSqlAdapter;
class User extends ModelManager
{
protected $table = 'users';
protected $adapter = PostgreSqlAdapter::class;
protected $primaryKey = 'id';
}
First Query
$user = User::find(1);
$users = User::all();
src/ModelManager.php for core methods (find(), create(), update(), etc.).src/Adapter/ for PostgreSQL/MySQL/SQLite implementations.// Create
$user = User::create(['name' => 'John', 'email' => 'john@example.com']);
// Read
$user = User::find(1);
$users = User::where('active', true)->get();
// Update
$user->update(['email' => 'new@example.com']);
// Delete
$user->delete();
Leverage Pomm’s query builder via fluent methods:
$activeUsers = User::query()
->where('active', true)
->orderBy('created_at', 'desc')
->limit(10)
->get();
Define has-one/many via belongsTo()/hasMany():
class Post extends ModelManager
{
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
}
Eager-load relationships:
$posts = Post::with('user')->get();
Wrap operations in a transaction:
User::transaction(function () {
$user = User::create([...]);
$user->posts()->create([...]);
});
Use Pomm’s event system for hooks:
User::creating(function ($model) {
$model->setAttribute('created_at', now());
});
Service Providers
Bind the manager to the container in AppServiceProvider:
$this->app->singleton(User::class, function ($app) {
return new User($app['pomm.connection']);
});
Eloquent-Like Facades Create a facade for convenience:
// UserFacade.php
class UserFacade extends Facade {
protected static function getFacadeAccessor() { return User::class; }
}
Register in config/app.php:
'aliases' => [
'User' => Conserto\Facades\UserFacade::class,
],
Custom Adapters
Extend ModelManager for domain-specific logic:
class AuditLog extends ModelManager
{
protected $table = 'audit_logs';
protected $fillable = ['action', 'user_id', 'changes'];
public function log($action, array $changes)
{
return $this->create([
'action' => $action,
'user_id' => auth()->id(),
'changes' => json_encode($changes),
]);
}
}
Adapter Mismatch
$adapter class matches your database (e.g., PostgreSqlAdapter for PostgreSQL).pomm-project/pomm adapter compatibility.Primary Key Assumptions
$primaryKey is defined. Omitting it may cause silent failures.protected $primaryKey = 'id'; unless using a composite key.Mass Assignment Risks
pomm-model-manager does not auto-fill mass-assignable attributes.$fillable or use create(['attr' => 'value']) safely.Lazy-Loading Relationships
with() selectively or implement load() for explicit loading.Transaction Rollback
try-catch or use PommProject\Pomm\Transaction\TransactionManager.Query Logging Enable Pomm’s query logging:
$connection = Pomm::connection();
$connection->getLogger()->setLevel(\Monolog\Logger::DEBUG);
Schema Mismatches
$table) matches the database.Connection Issues
config/database.php for correct DSN and credentials.$conn = Pomm::connection();
$conn->execute('SELECT 1');
Default Connection The package uses Laravel’s default database connection. Override via:
User::on('pomm_secondary')->find(1);
Caching Queries Pomm’s query cache is not enabled by default. Enable via:
$connection->setQueryCache(new \PommProject\Pomm\Cache\QueryCache());
Timezone Handling Pomm uses the system timezone. Force Laravel’s timezone:
date_default_timezone_set(config('app.timezone'));
Custom Query Builder
Extend Conserto\PommModelManager\Query\Builder to add domain-specific methods:
class CustomQueryBuilder extends Builder
{
public function activeOnly()
{
return $this->where('is_active', true);
}
}
Override in your model:
protected $queryBuilder = CustomQueryBuilder::class;
Model Events Use Pomm’s event system for pre/post hooks:
User::addListener('beforeInsert', function ($model) {
$model->setAttribute('slug', Str::slug($model->name));
});
Serialization
Override toArray() for custom serialization:
public function toArray()
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'created_at' => $this->created_at->format('Y-m-d'),
];
}
Soft Deletes Implement soft deletes via a trait:
trait SoftDeletes
{
protected $deletedAt = 'deleted_at';
public static function bootSoftDeletes()
{
static::addGlobalScope('softDeletes', function (Builder $builder) {
$builder->whereNull($builder->getModel()->deletedAt);
});
}
public function delete()
{
$this->setAttribute($this->deletedAt, now());
$this->save();
}
}
How can I help you explore Laravel packages today?