contenir / contenir-db-model
Attribute-mapped, typed-property data mapper built on php-db/phpdb
Requires
- php: ~8.3.0 || ~8.4.0 || ~8.5.0
- php-db/phpdb: 0.6.x-dev
- psr/container: ^1.1 || ^2.0
- psr/simple-cache: ^1.0 || ^2.0 || ^3.0
Requires (Dev)
- contenir/contenir-qa-tools: 0.1.x-dev
- infection/infection: ^0.34.1
- php-db/phpdb-mysql: ^0.4.0
- php-db/phpdb-pgsql: 0.1.x-dev
- php-db/phpdb-sqlite: ^0.2.0
- phpunit/phpunit: ^11.5.42
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- v2.x-dev
- v2.0.0-rc5
- v2.0.0-rc4
- v2.0.0-rc3
- v2.0.0-rc2
- v2.0.0-rc1
- 1.x-dev
- v1.0.4.4
- v1.0.4.3
- v1.0.4.2
- v1.0.4.1
- v1.0.4
- v1.0.3.13
- v1.0.3.12
- v1.0.3.11
- v1.0.3.10
- v1.0.3.9
- v1.0.3.8
- v1.0.3.7
- v1.0.3.6
- v1.0.3.5
- v1.0.3.4
- v1.0.3.3
- v1.0.3.2
- v1.0.3.1
- v1.0.3
- v1.0.2
- v1.0.1
- v1.0.0
- dev-chore/mago-1.57.0
- dev-ci/push-trigger
- dev-auto/issue-15
- dev-auto-dev/rejected-label
- dev-fix/simple-cache-v1
This package is auto-updated.
Last update: 2026-10-21 04:01:41 UTC
README
A small data mapper for php-db/phpdb.
Entities are plain PHP classes with typed properties, described by
attributes. There are no base classes and no magic __get/__set.
- Attribute mapping. Tables, columns, keys, versions and relations are declared on the class and validated up front.
- Typed values. Enums, dates, JSON, booleans and secrets are converted in both directions.
- An entity manager with an identity map, changed-column updates, optimistic locking and re-entrant transactions.
- Repositories with validated criteria, streaming and custom phpdb selects.
- Lazy relations, plus
preload()to avoid N+1 queries. Many-to-many relations can be ordered by join-table columns, such as a link'ssequence.
Status: 2.0 pre-release. 2.0 is a rewrite and is not compatible with 1.x. See UPGRADE-2.0.md. 1.x remains available from the
v1.0.*tags.
Requirements
- PHP 8.3, 8.4 or 8.5
php-db/phpdb0.6, plus the platform package for your database, such asphp-db/phpdb-mysqlorphp-db/phpdb-sqlitepsr/container,psr/simple-cache1.x, 2.x or 3.x
Installation
composer require contenir/contenir-db-model:^2.0@RC
The latest development version is v2.x-dev. Until php-db/phpdb 0.6.0
and this package's 2.0.0 are tagged, the consuming project needs "minimum-stability": "dev" and
"prefer-stable": true.
With laminas/laminas-component-installer, the ConfigProvider (Mezzio)
or Module (laminas-mvc) is registered automatically. See
container integration for configuration.
At a glance
use Contenir\Db\Model\Collection; use Contenir\Db\Model\EntityManager; use Contenir\Db\Model\Mapping\{Column, HasMany, Id, Table, Version}; #[Table('users')] final class User { #[Id(generated: true)] public ?int $id = null; #[Column] public string $email; #[Column('created_at')] public DateTimeImmutable $createdAt; #[Version] public int $version = 1; /** @var Collection<Order> */ #[HasMany(Order::class, foreignKey: 'user_id')] public Collection $orders; } $em = new EntityManager($adapter); $users = $em->getRepository(User::class); $user = $users->find(1); $user->email = 'new@example.com'; $em->save($user); // UPDATE users SET email = ?, version = 2 WHERE id = 1 AND version = 1 foreach ($user->orders as $order) { // loaded lazily, in one query }
Documentation
Read in this order:
- Mapping entities: attributes, keys, validation rules
- Type conversion: built-in and custom converters, nulls
- Persisting entities:
EntityManagersaves, deletes, locking and transactions - Repositories and finders: criteria, streaming, custom queries and repositories
- Relations: lazy collections,
LazyRelationsTrait,preload(), ordering by join-table columns - Identity map: one object per row, and memory in long-running processes
- Entity lifecycle: hydration, refresh, entities from rows without the database, and change tracking in detail
- Sensitive data:
SensitiveStringand redaction - Metadata caching: PSR-16 cache for production
- Container integration: configuration, factories, entity manager lifetime
Upgrading from 1.x: UPGRADE-2.0.md. Changes: CHANGELOG.md.
Console tools for generating entities from tables, upgrading 1.x entities and validating mappings against the schema are in contenir-db-model-tools.
llms.txt indexes these pages and lists the key rules for LLM
tooling.
Development
Mago is required. It is a standalone binary, installed with brew install mago or see the Mago docs.
composer install composer check # format check, lint, static analysis, unit + integration tests composer cs-fix # apply formatting and safe lint fixes composer test # unit suite (tests/Unit) composer test-integration # integration suite against in-memory SQLite (tests/Integration) composer test-coverage # line coverage to clover.xml (Xdebug or PCOV) composer test-coverage-branches # line + branch coverage across both suites (Xdebug)
The integration suite runs against in-memory SQLite by default. To run it
against MySQL or PostgreSQL, set DB_PLATFORM (and DB_HOST, DB_PORT,
DB_NAME, DB_USER, DB_PASSWORD as needed). compose.yml starts both
databases:
docker compose up -d DB_PLATFORM=mysql DB_PORT=33306 DB_PASSWORD=secret composer test-integration DB_PLATFORM=pgsql DB_PORT=55432 DB_USER=postgres DB_PASSWORD=secret composer test-integration
Every test recreates the fixture schema, including a crm schema or
database, so use a disposable database and a user allowed to create it.
CI runs the suite on SQLite, MySQL 8.4 and PostgreSQL 17.
test-coverage-branches runs each test directory in its own process and
merges the results, because Xdebug 3.4's --path-coverage intermittently
crashes on long runs. Pass -- --clover clover.xml or
-- --html build/coverage for report files.
QA configuration comes from contenir/contenir-qa-tools.
License
BSD-3-Clause. See LICENSE.md.