omnibridge / doctrine
The storage glue of omnibase sites, framework-free: Doctrine reading the structure described outside of it (omnisense/omnibridge's Omnibridge\Schema), the naming strategy that turns their entities into their tables, the UTC date types, and an entity manager built with them, for any framework reading
Requires
- php: >=8.2
- beberlei/doctrineextensions: ^1.0
- doctrine/dbal: ^4.2
- doctrine/orm: ^3.4
- omnisense/omnibridge: 1.x-dev
- scienta/doctrine-json-functions: ~4.3
- symfony/cache: ^7.0|^8.0
Requires (Dev)
- phpunit/phpunit: ^11.5
Suggests
- omnisense/omnibase: Omnibridge\Doctrine\Omnibase\: omnibase's persistence on Doctrine, moved from the core (its former Base\ names aliased by the core); loaded only with the core, which requires this package
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-07 06:02:05 UTC
README
The storage glue of omnibase sites, framework-free (plan 0, rule 13): what any
framework needs to map an omnibase site's database with Doctrine ORM and find
the same tables - and Doctrine reading the structure described outside of it
(audit "lesringostars face au master plan", R14; omnisense/omnibridge's
Omnibridge\Schema).
DeclarationDriver: a Doctrine mapping driver that builds a class's metadata from its declaration (Omnibridge\Schema\Declaration: what the class declares of its mapping, read without the ORM - or kept as data, a JSON file) instead of reading the attributes itself. It wraps the application's driver (an attribute driver, DoctrineBundle's chain), which still says which classes exist and maps a class the declarations do not hold. The metadata are those Doctrine's own attribute driver builds, to the property (the same calls on the ClassMetadata, in the same order):DeclarationDriverTestcompares every class of the fixtures both ways, from the attributes and from declarations that went through JSON.MetadataDescription::of($entityManager): what an entity manager maps, in the neutral form (Omnibridge\Schema\Description): each class as its metadata hold it, and the tables its SchemaTool would create.DescriptionTestproves it equal to the descriptionOmnibridge\Schema\Builderbuilds from the declarations alone; omnisense/omnibase's harness and lesringostars do the same over their entities, and lesringostars compares it with its database'sinformation_schema.NamingStrategy: Doctrine's naming strategy answered by the family's naming (Omnibridge\Schema\CamelCaseNaming, or theNaminggiven):App\Entity\Thread\TagisthreadTag,App\Entity\User\ProfileuserProfile,Thread::$tagsthe join tablethread_tags (thread_id, threadTag_id), a property its own name. Checked against every table and join table of lesringostars (tests/lesringostars-tables.json). omnibase'sBase\Database\Mapping\NamingStrategyextends it: one place says how a class becomes a table.Types::register():datetimeanddatetimetzwritten and read in UTC,utc_datetimeandutc_datetime_immutable, as omnibase registers them.EntityManagers::create($connection, $paths): an entity manager with both, attribute mapping, PHP's native lazy objects; itsconfigure:closure receives the configuration before the entity manager exists (a repository factory, the driver wrapped in aDeclarationDriver).
use Omnibridge\Doctrine\DeclarationDriver; use Omnibridge\Doctrine\EntityManagers; $entityManager = EntityManagers::create($connection, [$projectDir.'/src/Entity'], configure: function ($configuration) { $configuration->setMetadataDriverImpl(new DeclarationDriver($configuration->getMetadataDriverImpl())); });
Requires omnisense/omnibridge (the Schema), doctrine/orm ^3.4 and doctrine/dbal ^4.2 (tested on 3.7.5 and 4.5.0).
omnibase's persistence on Doctrine (Omnibridge\Doctrine\Omnibase\)
Since omnisense/omnibase's plan "omnibase agnostic", step F3 (2026-11-02), the core's Doctrine
classes live here, in src/Omnibase/: 142 classes moved by one rule - Base\Bridge\Doctrine\X is
Omnibridge\Doctrine\Omnibase\X, any other Base\X is Omnibridge\Doctrine\Omnibase\X:
- the Doctrine adapters of omnibridge's persistence contracts (
DoctrineUnitOfWork,DoctrineBackend,DoctrineRepositories,DoctrineShapes,QueryPages,MetadataDescription's use), the behaviours' Doctrine backends (Behaviour\*: row locks, conditional updates, the entity cache, bulk deletes, the vault, slugs, cache and order column) and their mapping hooks (Behaviour\DoctrineMappingHooks:#[Cache]'s regions,#[Vault]'s unique constraints,#[OrderColumn]'s field); - the mapping (
Mapping,MappingDriver,Configuration,Types,RepositoryFactory,Registry,MetadataSnapshot,Database\Mapping\ClassMetadataManipulator...), the DBAL types and adapters, the DQL walkers and functions, the trash and vault filters, the platform middleware, the schema describer; - the finder language's Doctrine compiler (
Database\Repository\ServiceEntityParser) andServiceEntityRepository, and the core's 81 repositories (Repository\*). The compiler reads what the core's finder adds at 5.0 and keeps a 4.x core's queries without it: groups and aggregates (step E2,finderReadsGroups()), an association compared by its key with no join (Finder\Key, step E2b:e.thread = :key_thread,IS NULL,IN;finderReadsKeys(), on whichCommentRepository::findVisible()/countVisible()are written).ComplaintRepositoryimplementsRepository\User\CoreComplaints: the core'sComplaintsunder 5.x,Entitiesunder 4.x, which has no such interface (step E2'); - the Doctrine listeners (
DatabaseSubscriber\*,EntitySubscriber\{Extension, Trasheable, Versionable, Setting}Subscriber) andDoctrineLocator(the registry and entity manager for the core's host code). - the console's Doctrine-typed tasks (omnisense/omnibase's plan "omnibase agnostic", step F5e, slice 3b;
Console\Task\*, on the core'sBase\Console\Report, so with omnibase 5.0):DoctrineDatabaseImport(a spreadsheet into the database, on the mapping's associations and discriminator maps),DoctrineSchemaCharsetandDoctrineArrayUpgrade(MySQL, on the DBAL connection); omnibridge/symfony'sdoctrine:database:import,doctrine:schema:charsetanddoctrine:array:upgraderun them.
This part is loaded only with omnisense/omnibase (in suggest here, not require). omnibase 4.x
requires this package; since omnibase 5.0 the application does (the core suggests it), and this package
requires the DQL functions the part registers, beberlei/doctrineextensions and
scienta/doctrine-json-functions. The core keeps the neutral half - the finder's
parser and AST, the repository interfaces, the shapes, the enumerations, the behaviours'
attributes - and aliases every former name (src/Resources/former-names.php), so the sites and
bundles change nothing. An entity's repositoryClass may name one of the core's repository
interfaces: RepositoryFactory builds the repository bound to it. This package's own suite tests the
generic part (and that it names nothing of omnibase, OmnibasePartTest); omnibase's part is tested in
the core's harness, which mounts this checkout. PHPStan leaves src/Omnibase to the core's analysis.
glitchr/base-plugin's Doctrine hook (audited 2026-10-17)
The hook rewrites three files of doctrine/orm:
ObjectHydrator: its anchor has been gone since doctrine/orm 3.6.7. The hook no longer patches anything there.SqlWalker(privatemadeprotected): not needed. omnibase's walkers use public methods only.ClassMetadataFactory(privatemadeprotected): still needed.- omnibase overrides
getShortName(), private upstream, so that default discriminator maps are keyed by class names. On doctrine/orm as published, its schema creation stops on a duplicated discriminator entry (user). - It also reads
$em, which a setter override could replace.
- omnibase overrides
This package needs no patch: an application mapping the tables with its own entities and explicit discriminator maps runs on doctrine/orm as published.
Tests
docker run --rm -v "$PWD":/app -w /app lesringostars-laravel-app vendor/bin/phpunit
18 tests: the vocabulary against doctrine/orm's attributes (every parameter, default and repeatability; every mapping attribute upstream known), the DeclarationDriver's metadata against the attribute driver's for a joined and a single-table hierarchy, nested join tables, lifecycle callbacks (from the attributes, and from declarations gone through JSON), the description built without Doctrine against Doctrine's and the tables it creates, the naming over lesringostars' tables, the UTC types.