Read from the package's own PHP files at the commit 3e9120ea9773: its namespaces, classes, interfaces and enums, their public constants, properties and methods with their PHPDoc, and the options its factories take. Nothing of it is run.
RuntimeclassThe registry through which an application's framework-free code reaches the contracts its host answers: an entity's getter, a value object, a screen's builder asks Runtime::urls(), ::access()... instead of a framework's services.
20 methods
SystemClockclassThe clock of the machine, the registry's clock when no host gave one (Runtime::clock()). A host gives its own, which a test can freeze (symfony/clock's, Laravel's dates).
1 method
AccessinterfaceWhat the visitor may do: an attribute (a role, "ROLE_ADMIN", or a permission a policy answers, "edit" on a subject) granted or not, and who the visitor is.
2 methods
EnvironmentinterfaceWhat the application runs as: its environment's name ("prod", "dev", "test"), whether it runs in debug, and its secret (the salt of what it hashes).
3 methods
FilesinterfaceThe stored files as the application sees them: where a file is served from and where PHP can read it, by its path in a storage. Nothing of how it is stored (Flysystem, a disk, a bucket): that stays with the storage.
4 methods
LocalesinterfaceThe languages of the site, language and country joined by a dash (fr-FR, en-GB): the one being answered, the default one, every one it speaks.
3 methods
RoutesinterfaceWhat the application's routes are, beyond making their addresses (Urls does that): the path a route is declared with, the route an address leads to, the icons a route is declared with.
3 methods
SessionsinterfaceThe visitor's session, as the application ends it: a user signed out when that user is the one signed in (the session forgotten, a remember-me cookie cleared), and told so; otherwise nothing here.
1 method
TokensinterfaceThe token a form carries for an intent, against cross-site requests: what a page's POST (or a script's request) sends back and its action checks.
2 methods
TranslationsinterfaceThe application's texts: a message in the page's language, from its catalogues (ICU messages: `{0}` and `{name}` placeholders, plurals), and whether the catalogues hold a key at all, which a code that tries several keys in turn needs.
2 methods
UrlsinterfaceAddresses, as an application asks for them: a route by its name, as a path (`path()`) or whole, with the scheme and the host (`url()`, for a mail, a feed, a link shared elsewhere), and a public file of the build (`asset()`).
3 methods
MissingContractExceptionclassA contract asked of Omnibridge\Runtime when no host filled it: loud, where a code that found no service would return null in silence.
2 methods
BuilderclassThe description of a set of entity classes, built from their declarations alone - no ORM asked: each class completed the way Doctrine completes its metadata (its parent's fields and relations inherited, a column named by the naming, a type guessed from the property's, a relation's default join columns and join table, the inheritance and its discriminator map), the application's rules applied at the moments Doctrine's listeners act, then the tables those classes make, as Doctrine's SchemaTool would create them (Builder\Tables).
6 methods
CamelCaseNamingclassThe omni family's names: App\Entity\Thread\Tag is the table threadTag, App\Entity\User\Profile userProfile - the App\ or Base\ prefix and the first Entity\ off, the rest in camel case -, a property its own column (lcfirst), Thread::$tags the join table thread_tags (thread_id, threadTag_id), a relation's join column <property>_id. A class that names its table (#[Table(name: ...)]) keeps that name. An index or a foreign key nobody named is named as DBAL names it - its prefix and the CRC32 of its table and columns, upper case, at most 64 characters (MySQL's limit) - so that the description finds the names of the existing tables.
9 methods · 3 constants
ColumnclassA column of a table, as the database holds it: its name, its type by the portable name the persistence layers share (string, integer, datetime, json... or an application's own type, thread_state), and what the type leaves open - length, precision and scale, fixed width, unsigned, nullable, default, auto-increment, the values of an enumeration or a set.
2 methods · 11 properties
DescriptionclassThe structure of an application's data, described once and outside any ORM (Marco's bridge principle, 2026-10-19: several persistence techniques, the same tables, the same columns): its entities - each class, its table, its fields and relations, its inheritance - and the tables they make, with their columns, keys, indexes and foreign keys.
6 methods · 2 properties
EntityclassAn entity class and how it is stored: its table, the entity it inherits from and the root of its hierarchy, how the hierarchy is stored, its identifier, its fields and its relations, by property (the inherited ones among them). A mapped superclass or an embeddable has no table of its own (kind), its fields are copied into the entities that extend or embed it.
4 methods · 10 properties · 3 constants
FieldclassA property of an entity kept in a column of its table: the column's name, its portable type, what the type leaves open, whether it is (part of) the identifier and how the identifier is generated, the PHP enumeration its values are read into; where it comes from - the entity it is inherited from (null: the entity's own, or a mapped superclass's or a trait's) and the class that declares the property.
2 methods · 14 properties
ForeignKeyclassA foreign key of a table: its columns, the table and columns they reference, what a deletion there does.
2 methods · 6 properties
IndexclassAn index of a table, unique or not, over its columns in order; flags such as fulltext.
2 methods · 4 properties
InheritanceclassHow a hierarchy of entities is stored: one table for all (single_table) or one per class joined on the identifier (joined); the column that tells a row's class, the value of each class in it, and the value of this one.
2 methods · 4 properties · 2 constants
JoinColumnclassA column holding the identifier of the related entity: its name, the column of the other table it references.
2 methods · 5 properties
JoinTableclassThe table between two entities of a many-to-many relation: its columns toward the owner, then toward the target.
2 methods · 3 properties
NaminginterfaceHow the structure names what its declarations leave unnamed: a class's table, a property's column, a relation's join columns and join table, an index or a foreign key nobody named. Doctrine's naming strategy asks the same questions (omnibridge/doctrine's NamingStrategy answers them with this); another persistence asks them here, and finds the same tables.
8 methods
RelationclassA property of an entity that holds other entities: its kind, its target, the property of the other side (mappedBy on the inverse side, inversedBy on the owning side), and on the owning side where the link is kept - the join columns of a to-one relation, the join table of a many-to-many one. Then how a collection is ordered and keyed, whether the relation is part of the identifier, where it comes from (as a Field).
3 methods · 13 properties · 4 constants
TableclassA table: its columns in the order the database holds them, its primary key, its indexes and unique indexes, its foreign keys, by name.
3 methods · 5 properties
DraftclassA class of the description while it is built: what its parent gave it, then what its declaration adds, then what the rules add - each mapping in plain arrays, completed as it is added (a column's name, a type guessed from the property, a relation's join columns or join table), the way an ORM's metadata complete themselves. The Builder turns it into an Entity once it is whole; a Rule (an application's own conventions) changes it on the way, as an ORM's listener would.
13 methods · 17 properties · 1 constant
RuleinterfaceAn application's own convention over the structure its classes declare - what an ORM's listeners add to its metadata (omnibase: the translations' relations, the discriminator values, a vault's unique key) - applied to each class while the description is built, at the three moments an ORM gives its listeners: before the class's declaration is read (its inheritance and its parent's state are there), once it is read, and once the class is whole (Doctrine's loadClassMetadata).
3 methods
MySqlSchemaclassA MySQL database's schema read from its information_schema (through PDO, read-only, no ORM), and compared with a description: every table, then in each every column - its SQL type as MySQL 8 writes it, nullable, default, auto-increment -, the primary key, each index and unique index by name and columns, each foreign key by name, columns, referenced table and columns, and what a deletion does. An independent check that the description is the database's schema: nothing of the persistence that made the tables is asked.
7 methods · 1 property
AttributeclassOne mapping attribute as an entity carries it, read without its class: its name in the vocabulary (Column, ManyToOne, JoinColumn...) and its arguments by parameter name, as written - a positional argument named after the parameter it fills, a nested attribute (a JoinTable's join columns) an Attribute itself. get() adds the vocabulary's default of an argument left out.
6 methods · 2 properties
AttributeReaderclassReads an entity class's mapping attributes into its ClassDeclaration, by reflection and without instantiating them: an attribute is its name and its arguments (ReflectionAttribute::getArguments()), so its class need not exist - the ORM need not be installed to read what the entities declare.
1 method
ClassDeclarationclassWhat an entity class declares of its mapping, read from its attributes and nothing else: the class's own attributes (Entity, Table, InheritanceType...), then each property in the order reflection lists them - the inherited ones among them, with the class that declares each - and each public method carrying a lifecycle attribute. Nothing is resolved here (no default name, no type guessed): that is the description's (Omnibridge\Schema\Description), and a persistence's that reads the declaration as its mapping.
7 methods · 4 properties
DeclarationSetclassDeclarations kept as data, by class: read back from their plain form (toArray(), a JSON file), or gathered from another source.
6 methods
DeclarationsinterfaceWhere the declarations of the entity classes come from: their attributes (AttributeReader), or a set kept as data (DeclarationSet: a file written once, another vocabulary turned into this one). A persistence bridge maps the classes from it - omnibridge/doctrine's DeclarationDriver gives Doctrine its metadata from it - and never reads the classes' attributes itself.
1 method
MemberclassA property or a method of an entity class with the mapping attributes it carries, and the class that declares it.
5 methods · 3 properties
VocabularyclassThe mapping attributes the entities are written with - those of the Doctrine\ORM\Mapping namespace, the vocabulary omnibase's entities and their applications' carry - as plain data: each attribute's parameters in the order of its constructor, with their defaults, and whether it may be written more than once. With it a declaration is read without the attributes' classes (a positional argument gets its parameter's name, a left-out one its default), so without the ORM installed.
5 methods · 5 constants
Omnibridge
Runtime class
class Runtime Runtime.php:52
The registry through which an application's framework-free code reaches the contracts its host answers: an entity's getter, a value object, a screen's builder asks Runtime::urls(), ::access()... instead of a framework's services.
Each contract is asked by its interface's name. A host fills the registry once, at boot:
- with a PSR-11 container whose ids are those names (setContainer()): under
Symfony, a service locator (omnisense/omnibase's
base.contracts); under Laravel, the application itself, its bindings named by the interfaces (omnibridge/laravel); - or one service at a time (set()), which wins over the container's.
A contract is one interface whatever name it is asked by: a former name kept by alias() (Base\Contract\Urls, Omnibridge\Twig\Contract\Urls) is the same contract, the same service. The container is asked by the interface's own name first, then by the name asked, then by its former names - a host that still binds a former name only is found by the new one.
A contract asked and not filled throws MissingContractException, except the clock, which is the machine's (SystemClock) when none was given; find() answers null instead, for a caller that can do without.
A different container means a different kernel: what was resolved from the previous one is forgotten, the services set by hand are kept.
Not final: an application family adds its own contracts' accessors in a class of its own over the same registry (omnisense/omnibase's Base\Contract\Runtime: its parameters, nouns, media, pictures, texts and mailer). The state is this class's, shared by any such class.
Runtime::alias()
public static function alias(string $contract, string $former): voidKeeps a contract (or any class of a family) reachable under a former name: class_alias() - an alternate name, not a subclass - and the registry told, so that a service bound under the former name is found by the new one. Declared by the package that owned the name, when Composer's autoloader is loaded (its autoload.files), never on demand: PHP autoloads nothing for a parameter's type or an instanceof.
Runtime::formerNames()
public static function formerNames(string $contract): arrayThe former names a contract is still reachable by.
Runtime::setContainer()
public static function setContainer(?ContainerInterface $container): voidRuntime::getContainer()
public static function getContainer(): ?ContainerInterfaceRuntime::set()
public static function set(string $contract, ?object $service): voidOne contract's service, ahead of the container's; null takes it back.
Runtime::has()
public static function has(string $contract): boolRuntime::find()
public static function find(string $contract): ?objectRuntime::get()
public static function get(string $contract): objectRuntime::reset()
public static function reset(): voidEverything forgotten: no container, nothing set (a test's tearDown); the former names stay, being declarations.
Runtime::urls()
public static function urls(): UrlsRuntime::translations()
public static function translations(): TranslationsRuntime::locales()
public static function locales(): LocalesRuntime::access()
public static function access(): AccessRuntime::sessions()
public static function sessions(): SessionsThe visitor's session: a user signed out when it is the one signed in.
Runtime::tokens()
public static function tokens(): TokensRuntime::files()
public static function files(): FilesRuntime::routes()
public static function routes(): RoutesWhat the routes are beyond their addresses: a route's path, an address's route, a route's icons.
Runtime::environment()
public static function environment(): EnvironmentWhat the application runs as: its environment's name, debug, its secret.
Runtime::clock()
public static function clock(): ClockInterfaceThe host's clock, or the machine's when none was given.
Runtime::events()
public static function events(): EventDispatcherInterfaceSystemClock class
final class SystemClock implements ClockInterface SystemClock.php:15
The clock of the machine, the registry's clock when no host gave one (Runtime::clock()). A host gives its own, which a test can freeze (symfony/clock's, Laravel's dates).
Formerly Base\Contract\SystemClock, an alias removed at omnibase 4's final pass.
SystemClock::now()
public function now(): \DateTimeImmutableOmnibridge\Contract
Access interface
interface Access Access.php:16
What the visitor may do: an attribute (a role, "ROLE_ADMIN", or a permission a policy answers, "edit" on a subject) granted or not, and who the visitor is.
Generic: Symfony's authorization checker and token storage, Laravel's gate and guard answer the same two questions.
Formerly Base\Contract\Access, an alias removed at omnibase 4's final pass.
Access::isGranted()
public function isGranted(mixed $attribute, mixed $subject = null): boolWhether the visitor holds the attribute, on the subject when one is given; false for nobody signed in unless the attribute is granted to anyone.
Access::getUser()
public function getUser(): ?objectThe visitor signed in (an application's user), null for nobody.
Environment interface
interface Environment Environment.php:16
What the application runs as: its environment's name ("prod", "dev", "test"), whether it runs in debug, and its secret (the salt of what it hashes).
Generic: Symfony's kernel.environment, kernel.debug and kernel.secret; Laravel's APP_ENV, app.debug and app.key.
Formerly Base\Contract\Environment, an alias removed at omnibase 4's final pass.
Environment::name()
public function name(): stringThe environment's name: "prod", "dev", "test".
..
Environment::isDebug()
public function isDebug(): boolEnvironment::secret()
public function secret(): stringThe application's secret, which salts what it hashes.
Files interface
interface Files Files.php:17
The stored files as the application sees them: where a file is served from and where PHP can read it, by its path in a storage. Nothing of how it is stored (Flysystem, a disk, a bucket): that stays with the storage.
Generic: a storage is named as the application's configuration names it ("local.uploads", "s3.private"...), null for the default one; each bridge maps those names to its host's storages (Flysystem's, Laravel's disks).
Formerly Base\Contract\Files, an alias removed at omnibase 4's final pass.
Files::publicPath()
public function publicPath(string $path, ?string $storage = null): ?stringA stored file's path under the public directory, which the web server serves, or for a remote storage the address it is served from; null when it has neither (a missing file, a private storage).
Files::publicUrl()
public function publicUrl(string $path, ?string $storage = null): ?stringThe web address of a stored file (/uploads/...); null as publicPath().
Files::localPath()
public function localPath(string $path, ?string $storage = null): ?stringThe file's path on this machine (a local storage, its root prefixed), null where there is no local file behind it (a remote storage).
Files::isRemote()
public function isRemote(?string $storage = null): boolWhether the storage is remote: no file on this machine behind its paths.
Locales interface
interface Locales Locales.php:16
The languages of the site, language and country joined by a dash (fr-FR, en-GB): the one being answered, the default one, every one it speaks.
Generic: every host has a current and a default locale. A bridge that names
them otherwise (Laravel's fr) gives them in this form. Named in the
plural so as not to shadow PHP's \Locale where it is imported.
Formerly Base\Contract\Locales, an alias removed at omnibase 4's final pass.
Locales::getLocale()
public function getLocale(): stringThe locale of the request being answered (or of the command), fr-FR.
Locales::getDefaultLocale()
public function getDefaultLocale(): stringThe site's default locale, the language its texts are written in first.
Locales::getAvailableLocales()
public function getAvailableLocales(): arrayEvery locale the site speaks, the default first.
Routes interface
interface Routes Routes.php:17
What the application's routes are, beyond making their addresses (Urls does that): the path a route is declared with, the route an address leads to, the icons a route is declared with.
Generic: every router knows a route's pattern and matches an address. Icons are a route's metadata where the host keeps some (omnibase's #[Iconize] under Symfony); a host without answers null.
Formerly Base\Contract\Routes, an alias removed at omnibase 4's final pass.
Routes::pattern()
public function pattern(string $name): ?stringThe path the route is declared with ("/articles/{slug}"), null for no such route.
Routes::match()
public function match(string $url): ?stringThe name of the route an address leads to (a localized route's with its language, "article.en", when it is not the default one), null when none does.
Routes::icons()
public function icons(string $name): ?arrayThe icons of a route, in the page's language when it has several; null for none.
Sessions interface
interface Sessions Sessions.php:15
The visitor's session, as the application ends it: a user signed out when that user is the one signed in (the session forgotten, a remember-me cookie cleared), and told so; otherwise nothing here.
Generic: Symfony's token storage, Laravel's guard logout().
Formerly Base\Contract\Sessions, an alias removed at omnibase 4's final pass.
Sessions::signOut()
public function signOut(object $user): boolSigns the user out if it is the visitor signed in here; false when it is not (nobody, or someone else).
Tokens interface
interface Tokens Tokens.php:16
The token a form carries for an intent, against cross-site requests: what a page's POST (or a script's request) sends back and its action checks.
Generic: Symfony's CSRF token manager (one token per intent), Laravel's session token (one for every intent). A token made by one host is checked by that host only.
Formerly Base\Contract\Tokens, an alias removed at omnibase 4's final pass.
Tokens::csrf()
public function csrf(string $intent): stringThe token of that intent ("profile_edit", "delete_12"...) for the visitor's session.
Tokens::isValid()
public function isValid(string $intent, ?string $token): boolWhether a token sent back is the visitor's token of that intent: what an action checks before acting (Symfony's isCsrfTokenValid(), Laravel's VerifyCsrfToken). A missing or empty token is never valid.
Translations interface
interface Translations Translations.php:22
The application's texts: a message in the page's language, from its
catalogues (ICU messages: {0} and {name} placeholders, plurals), and
whether the catalogues hold a key at all, which a code that tries several
keys in turn needs.
Generic: every host has message catalogues and can tell whether one holds a key (Symfony's catalogue, Laravel's Translator::has()). omnibridge/laravel's CatalogueTranslations reads the ICU catalogues with symfony/translation; omnisense/omnibase's Base\Bridge\Symfony\TranslatorTranslations is its translator.
Formerly Omnibridge\Twig\Contract\Translations (trans() alone) and Base\Contract\Translations (with exists()), aliases removed at omnibase 4's final pass: one interface, so one object answers a page and the application's code alike.
Translations::trans()
public function trans(string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): stringTranslations::exists()
public function exists(string $id, ?string $domain = null, ?string $locale = null): boolWhether the catalogue of that locale (the page's when none is given) holds the key in that domain, its fallback catalogues included.
Urls interface
interface Urls Urls.php:18
Addresses, as an application asks for them: a route by its name, as a path
(path()) or whole, with the scheme and the host (url(), for a mail, a
feed, a link shared elsewhere), and a public file of the build (asset()).
Generic: every host has routes with names and serves public files. Each bridge answers with its own router and asset packages (omnibridge/laravel's RouterUrls, omnisense/omnibase's Base\Bridge\Symfony\RouterUrls); a page rendered by Twig asks the same object (omnibridge/twig's ContractExtension).
Formerly Omnibridge\Twig\Contract\Urls and Base\Contract\Urls, aliases removed at omnibase 4's final pass.
Urls::path()
public function path(string $name, array $parameters = []): stringUrls::url()
public function url(string $name, array $parameters = []): stringThe same route, whole (scheme and host).
Urls::asset()
public function asset(string $path): stringOmnibridge\Exception
MissingContractException class
final class MissingContractException extends LogicException MissingContractException.php:12
A contract asked of Omnibridge\Runtime when no host filled it: loud, where a code that found no service would return null in silence.
Formerly Base\Exception\MissingContractException, an alias removed at omnibase 4's final pass.
MissingContractException::for()
public static function for(string $contract, array $formerNames = []): selfMissingContractException::notAn()
public static function notAn(string $contract, object $service): selfOmnibridge\Schema
Builder class
final class Builder Builder.php:31
The description of a set of entity classes, built from their declarations alone - no ORM asked: each class completed the way Doctrine completes its metadata (its parent's fields and relations inherited, a column named by the naming, a type guessed from the property's, a relation's default join columns and join table, the inheritance and its discriminator map), the application's rules applied at the moments Doctrine's listeners act, then the tables those classes make, as Doctrine's SchemaTool would create them (Builder\Tables).
The same description as omnibridge/doctrine's MetadataDescription reads from an entity manager over the same classes: that is the proof that the structure is described outside the ORM, and that another persistence can map the same tables from it.
A generated identifier with the AUTO strategy is the database's own (identity: an auto-increment column, MySQL's); $autoGenerator says another.
Builder::__construct()
public function __construct(readonly Declarations $declarations = new AttributeReader(), readonly Naming $naming = new CamelCaseNaming(), readonly array $rules = [], readonly string $autoGenerator = 'identity')Builder::build()
public function build(iterable $classNames): Description$classNamesthe classes to describe (a folder's, an ORM driver's): the entities, their mapped superclasses
Builder::classes()
public function classes(): array- Returns
the classes described, in the order they were given
Builder::naming()
public function naming(): NamingBuilder::declaration()
public function declaration(string $className): ?ClassDeclarationBuilder::draft()
public function draft(string $className): DraftThe class as described so far, its parents first: what an ORM's metadata factory hands out.
CamelCaseNaming class
class CamelCaseNaming implements Naming CamelCaseNaming.php:21
The omni family's names: App\Entity\Thread\Tag is the table threadTag, App\Entity\User\Profile userProfile - the App\ or Base\ prefix and the first Entity\ off, the rest in camel case -, a property its own column (lcfirst), Thread::$tags the join table thread_tags (thread_id, threadTag_id), a relation's join column <property>_id. A class that names its table (#[Table(name: ...)]) keeps that name. An index or a foreign key nobody named is named as DBAL names it - its prefix and the CRC32 of its table and columns, upper case, at most 64 characters (MySQL's limit) - so that the description finds the names of the existing tables.
omnibridge/doctrine's NamingStrategy (Doctrine's) and omnisense/omnibase's answer with this class: one place says how a class becomes a table.
const TABLE_NAME_SIZE = 64const TABLE_I18N_SUFFIX = 'Intl'const IDENTIFIER_SIZE = 64
CamelCaseNaming::__construct()
public function __construct(readonly array $prefixes = ['App\\', 'Base\\'])$prefixesthe namespaces a class's table name leaves out
CamelCaseNaming::classToTableName()
public function classToTableName(string $className): stringCamelCaseNaming::propertyToColumnName()
public function propertyToColumnName(string $propertyName, string $className): stringCamelCaseNaming::embeddedFieldToColumnName()
public function embeddedFieldToColumnName(string $propertyName, string $embeddedColumnName, string $className, string $embeddedClassName): stringCamelCaseNaming::referenceColumnName()
public function referenceColumnName(): stringCamelCaseNaming::joinColumnName()
public function joinColumnName(string $propertyName, string $className): stringCamelCaseNaming::joinTableName()
public function joinTableName(string $sourceEntity, string $targetEntity, string $propertyName): stringCamelCaseNaming::joinKeyColumnName()
public function joinKeyColumnName(string $entityName, ?string $referencedColumnName): stringCamelCaseNaming::generatedName()
public function generatedName(string $table, array $columns, string $prefix): stringColumn class
final class Column Column.php:12
A column of a table, as the database holds it: its name, its type by the portable name the persistence layers share (string, integer, datetime, json... or an application's own type, thread_state), and what the type leaves open - length, precision and scale, fixed width, unsigned, nullable, default, auto-increment, the values of an enumeration or a set.
public readonly string $namepublic readonly string $typepublic readonly bool $nullablepublic readonly ?int $lengthpublic readonly ?int $precisionpublic readonly ?int $scalepublic readonly bool $fixedpublic readonly bool $unsignedpublic readonly bool $autoincrementpublic readonly string|int|float|bool|null $defaultpublic readonly ?array $valuesthe values an enumeration or a set column admits, in the order its type gives them
Column::__construct()
public function __construct(public readonly string $name, public readonly string $type, public readonly bool $nullable = false, public readonly ?int $length = null, public readonly ?int $precision = null, public readonly ?int $scale = null, public readonly bool $fixed = false, public readonly bool $unsigned = false, public readonly bool $autoincrement = false, public readonly string|int|float|bool|null $default = null, public readonly ?array $values = null)$valuesthe values an enumeration or a set column admits, in the order its type gives them
Column::fromArray()
public static function fromArray(array $data): selfDescription class
final class Description Description.php:17
The structure of an application's data, described once and outside any ORM (Marco's bridge principle, 2026-10-19: several persistence techniques, the same tables, the same columns): its entities - each class, its table, its fields and relations, its inheritance - and the tables they make, with their columns, keys, indexes and foreign keys.
A persistence bridge reads it: omnibridge/doctrine builds Doctrine's metadata from the declarations it comes from and gives it back from an entity manager; another persistence (Eloquent...) maps the same tables with it. toArray() is its plain form, a JSON file's; fromArray() reads it back.
public readonly array $entitiesby class
public readonly array $tablesby name
Description::__construct()
public function __construct(public readonly array $entities = [], public readonly array $tables = [])$entitiesby class
$tablesby name
Description::entity()
public function entity(string $class): Entity- Throws
OutOfBoundsException for a class the description does not hold
Description::table()
public function table(string $name): Table- Throws
OutOfBoundsException for a table the description does not hold
Description::fromArray()
public static function fromArray(array $data): selfDescription::toJson()
public function toJson(): stringDescription::fromJson()
public static function fromJson(string $json): selfEntity class
final class Entity Entity.php:12
An entity class and how it is stored: its table, the entity it inherits from and the root of its hierarchy, how the hierarchy is stored, its identifier, its fields and its relations, by property (the inherited ones among them). A mapped superclass or an embeddable has no table of its own (kind), its fields are copied into the entities that extend or embed it.
const ENTITY = 'entity'const MAPPED_SUPERCLASS = 'mapped_superclass'const EMBEDDABLE = 'embeddable'public readonly string $classpublic readonly ?string $tablepublic readonly string $kindpublic readonly ?string $parentpublic readonly ?string $rootpublic readonly ?Inheritance $inheritancepublic readonly array $identifierthe properties
public readonly array $fieldsby property
public readonly array $relationsby property
public readonly array $subclassesthe entities below it in its hierarchy
Entity::__construct()
public function __construct(public readonly string $class, public readonly ?string $table, public readonly string $kind = self::ENTITY, public readonly ?string $parent = null, public readonly ?string $root = null, public readonly ?Inheritance $inheritance = null, public readonly array $identifier = [], public readonly array $fields = [], public readonly array $relations = [], public readonly array $subclasses = [])$identifierthe properties
$fieldsby property
$relationsby property
$subclassesthe entities below it in its hierarchy
Entity::field()
public function field(string $property): Field- Throws
OutOfBoundsException for a property that is no field
Entity::relation()
public function relation(string $property): Relation- Throws
OutOfBoundsException for a property that is no relation
Entity::fromArray()
public static function fromArray(array $data): selfField class
final class Field Field.php:15
A property of an entity kept in a column of its table: the column's name, its portable type, what the type leaves open, whether it is (part of) the identifier and how the identifier is generated, the PHP enumeration its values are read into; where it comes from - the entity it is inherited from (null: the entity's own, or a mapped superclass's or a trait's) and the class that declares the property.
public readonly string $propertypublic readonly string $columnpublic readonly string $typepublic readonly bool $nullablepublic readonly ?int $lengthpublic readonly ?int $precisionpublic readonly ?int $scalepublic readonly bool $uniquepublic readonly array $optionswhat else the column says (default, unsigned, fixed, comment, charset...)
public readonly bool $idpublic readonly ?string $generatedpublic readonly ?string $enumpublic readonly ?string $inheritedFrompublic readonly ?string $declaredIn
Field::__construct()
public function __construct(public readonly string $property, public readonly string $column, public readonly string $type, public readonly bool $nullable = false, public readonly ?int $length = null, public readonly ?int $precision = null, public readonly ?int $scale = null, public readonly bool $unique = false, public readonly array $options = [], public readonly bool $id = false, public readonly ?string $generated = null, public readonly ?string $enum = null, public readonly ?string $inheritedFrom = null, public readonly ?string $declaredIn = null)$optionswhat else the column says (default, unsigned, fixed, comment, charset...)
Field::fromArray()
public static function fromArray(array $data): selfForeignKey class
final class ForeignKey ForeignKey.php:6
A foreign key of a table: its columns, the table and columns they reference, what a deletion there does.
public readonly string $namepublic readonly array $columnspublic readonly string $tablepublic readonly array $referencedColumnspublic readonly ?string $onDeletepublic readonly ?string $onUpdate
ForeignKey::__construct()
public function __construct(public readonly string $name, public readonly array $columns, public readonly string $table, public readonly array $referencedColumns, public readonly ?string $onDelete = null, public readonly ?string $onUpdate = null)ForeignKey::fromArray()
public static function fromArray(array $data): selfIndex class
final class Index Index.php:6
An index of a table, unique or not, over its columns in order; flags such as fulltext.
public readonly string $namepublic readonly array $columnspublic readonly bool $uniquepublic readonly array $flags
Index::__construct()
public function __construct(public readonly string $name, public readonly array $columns, public readonly bool $unique = false, public readonly array $flags = [])Index::fromArray()
public static function fromArray(array $data): selfInheritance class
final class Inheritance Inheritance.php:10
How a hierarchy of entities is stored: one table for all (single_table) or one per class joined on the identifier (joined); the column that tells a row's class, the value of each class in it, and the value of this one.
const SINGLE_TABLE = 'single_table'const JOINED = 'joined'public readonly string $typepublic readonly Column $columnpublic readonly array $mapdiscriminator value => class
public readonly ?string $value
Inheritance::__construct()
public function __construct(public readonly string $type, public readonly Column $column, public readonly array $map = [], public readonly ?string $value = null)$mapdiscriminator value => class
Inheritance::fromArray()
public static function fromArray(array $data): selfJoinColumn class
final class JoinColumn JoinColumn.php:6
A column holding the identifier of the related entity: its name, the column of the other table it references.
public readonly string $namepublic readonly string $referencedColumnpublic readonly bool $nullablepublic readonly bool $uniquepublic readonly ?string $onDelete
JoinColumn::__construct()
public function __construct(public readonly string $name, public readonly string $referencedColumn = 'id', public readonly bool $nullable = true, public readonly bool $unique = false, public readonly ?string $onDelete = null)JoinColumn::fromArray()
public static function fromArray(array $data): selfJoinTable class
final class JoinTable JoinTable.php:6
The table between two entities of a many-to-many relation: its columns toward the owner, then toward the target.
public readonly string $namepublic readonly array $joinColumnstoward the entity that owns the relation
public readonly array $inverseJoinColumnstoward its target
JoinTable::__construct()
public function __construct(public readonly string $name, public readonly array $joinColumns = [], public readonly array $inverseJoinColumns = [])$joinColumnstoward the entity that owns the relation
$inverseJoinColumnstoward its target
JoinTable::fromArray()
public static function fromArray(array $data): selfNaming interface
interface Naming Naming.php:12
How the structure names what its declarations leave unnamed: a class's table, a property's column, a relation's join columns and join table, an index or a foreign key nobody named. Doctrine's naming strategy asks the same questions (omnibridge/doctrine's NamingStrategy answers them with this); another persistence asks them here, and finds the same tables.
Naming::classToTableName()
public function classToTableName(string $className): stringNaming::propertyToColumnName()
public function propertyToColumnName(string $propertyName, string $className): stringNaming::embeddedFieldToColumnName()
public function embeddedFieldToColumnName(string $propertyName, string $embeddedColumnName, string $className, string $embeddedClassName): stringNaming::referenceColumnName()
public function referenceColumnName(): stringNaming::joinColumnName()
public function joinColumnName(string $propertyName, string $className): stringNaming::joinTableName()
public function joinTableName(string $sourceEntity, string $targetEntity, string $propertyName): stringNaming::joinKeyColumnName()
public function joinKeyColumnName(string $entityName, ?string $referencedColumnName): stringNaming::generatedName()
public function generatedName(string $table, array $columns, string $prefix): stringThe name of an index (prefix idx), a unique index (uniq) or a foreign key (fk) its declaration does not name, from its table and columns.
Relation class
final class Relation Relation.php:13
A property of an entity that holds other entities: its kind, its target, the property of the other side (mappedBy on the inverse side, inversedBy on the owning side), and on the owning side where the link is kept - the join columns of a to-one relation, the join table of a many-to-many one. Then how a collection is ordered and keyed, whether the relation is part of the identifier, where it comes from (as a Field).
const ONE_TO_ONE = 'one_to_one'const MANY_TO_ONE = 'many_to_one'const ONE_TO_MANY = 'one_to_many'const MANY_TO_MANY = 'many_to_many'public readonly string $propertypublic readonly string $kindpublic readonly string $targetpublic readonly bool $owningpublic readonly ?string $mappedBypublic readonly ?string $inversedBypublic readonly array $joinColumnspublic readonly ?JoinTable $joinTablepublic readonly array $orderByproperty => ASC|DESC
public readonly ?string $indexBypublic readonly bool $idpublic readonly ?string $inheritedFrompublic readonly ?string $declaredIn
Relation::__construct()
public function __construct(public readonly string $property, public readonly string $kind, public readonly string $target, public readonly bool $owning, public readonly ?string $mappedBy = null, public readonly ?string $inversedBy = null, public readonly array $joinColumns = [], public readonly ?JoinTable $joinTable = null, public readonly array $orderBy = [], public readonly ?string $indexBy = null, public readonly bool $id = false, public readonly ?string $inheritedFrom = null, public readonly ?string $declaredIn = null)$orderByproperty => ASC|DESC
Relation::isToOne()
public function isToOne(): boolRelation::fromArray()
public static function fromArray(array $data): selfTable class
final class Table Table.php:9
A table: its columns in the order the database holds them, its primary key, its indexes and unique indexes, its foreign keys, by name.
public readonly string $namepublic readonly array $columnsby name
public readonly array $primaryKeythe columns
public readonly array $indexesby name, the unique ones among them
public readonly array $foreignKeysby name
Table::__construct()
public function __construct(public readonly string $name, public readonly array $columns = [], public readonly array $primaryKey = [], public readonly array $indexes = [], public readonly array $foreignKeys = [])$columnsby name
$primaryKeythe columns
$indexesby name, the unique ones among them
$foreignKeysby name
Table::column()
public function column(string $name): Column- Throws
OutOfBoundsException for a column the table does not hold
Table::fromArray()
public static function fromArray(array $data): selfOmnibridge\Schema\Builder
Draft class
final class Draft Draft.php:25
A class of the description while it is built: what its parent gave it, then what its declaration adds, then what the rules add - each mapping in plain arrays, completed as it is added (a column's name, a type guessed from the property, a relation's join columns or join table), the way an ORM's metadata complete themselves. The Builder turns it into an Entity once it is whole; a Rule (an application's own conventions) changes it on the way, as an ORM's listener would.
Fields: property => {fieldName, columnName, type, length, precision, scale, nullable, unique, index, options, id, enumType, inherited, declared}; relations: property => {fieldName, type (a Relation::* kind), targetEntity, sourceEntity, mappedBy, inversedBy, isOwningSide, joinColumns (list of {name, referencedColumnName, nullable, unique, onDelete}), joinTable ({name, joinColumns, inverseJoinColumns}), orderBy, indexBy, id, inherited, declared}. Indexes and unique constraints by name (or position): {columns} or {fields}, flags, options.
const NONE = 'none'public array $parentClasses = []public string $rootEntityNamepublic bool $isMappedSuperclass = falsepublic bool $isEmbeddedClass = falsepublic array $tablepublic string $inheritanceType = self::NONEpublic ?array $discriminatorColumn = nullpublic array $discriminatorMap = []public ?string $discriminatorValue = nullpublic array $subClasses = []public string $generatorType = self::NONEauto, identity, sequence, none or custom
public array $identifier = []public array $identifierPositions = []public array $fieldMappings = []public array $fieldNames = []public array $associationMappings = []public readonly string $name
Draft::__construct()
public function __construct(public readonly string $name, readonly Naming $naming)Draft::naming()
public function naming(): NamingDraft::isInheritanceTypeNone()
public function isInheritanceTypeNone(): boolDraft::isInheritanceTypeSingleTable()
public function isInheritanceTypeSingleTable(): boolDraft::isInheritanceTypeJoined()
public function isInheritanceTypeJoined(): boolDraft::isRootEntity()
public function isRootEntity(): boolDraft::hasField()
public function hasField(string $property): boolDraft::hasAssociation()
public function hasAssociation(string $property): boolDraft::mapField()
public function mapField(array $mapping): voidA field's mapping as declared ({fieldName, type?, columnName?, length?, nullable?, id?...}), completed and added.
Draft::mapRelation()
public function mapRelation(array $mapping): voidA relation's mapping as declared ({fieldName, type, targetEntity?, mappedBy?, inversedBy?, joinColumns?, joinTable?...}), completed and added.
Draft::setDiscriminatorMap()
public function setDiscriminatorMap(array $map): voidThe parent's discriminator map added to this class's: its own value found there, its subclasses among them.
Draft::addSubClass()
public function addSubClass(string $className): voidDraft::setIdentifier()
public function setIdentifier(array $identifier, array $positions): voidRule interface
interface Rule Rule.php:17
An application's own convention over the structure its classes declare - what an ORM's listeners add to its metadata (omnibase: the translations' relations, the discriminator values, a vault's unique key) - applied to each class while the description is built, at the three moments an ORM gives its listeners: before the class's declaration is read (its inheritance and its parent's state are there), once it is read, and once the class is whole (Doctrine's loadClassMetadata).
Rule::before()
public function before(Draft $class, ClassDeclaration $declaration, Builder $builder): voidRule::declared()
public function declared(Draft $class, ClassDeclaration $declaration, Builder $builder): voidRule::loaded()
public function loaded(Draft $class, ClassDeclaration $declaration, Builder $builder): voidOmnibridge\Schema\Database
MySqlSchema class
final class MySqlSchema MySqlSchema.php:24
A MySQL database's schema read from its information_schema (through PDO, read-only, no ORM), and compared with a description: every table, then in each every column - its SQL type as MySQL 8 writes it, nullable, default, auto-increment -, the primary key, each index and unique index by name and columns, each foreign key by name, columns, referenced table and columns, and what a deletion does. An independent check that the description is the database's schema: nothing of the persistence that made the tables is asked.
A column's expected SQL type comes from its portable type (columnType(): string(255) is varchar(255), text longtext, boolean tinyint(1), every date and time datetime...); an application's own types are given by name, each a closure from the column to its SQL type (enum('A','B') for an enumeration). Collations, character sets and comments are not compared.
public readonly array $tables
MySqlSchema::of()
public static function of(array $tables, array $types = []): selfA schema kept as data (read() once, written to a file), or hand-written: the tables as read() gives them.
$tablesby name
MySqlSchema::read()
public static function read(\PDO $pdo, ?string $database = null, array $ignore = [], array $types = []): self$ignoretables of the database the description does not hold (doctrine_migration_versions...)
$typesthe SQL type of a column of an application's own type, by the type's name
MySqlSchema::differences()
public function differences(Description $description): arrayEvery difference between the description's tables and the database's, one a line ("table.column: type varchar(255) / varchar(191)"); none when the description is the database's schema.
MySqlSchema::sameType()
public static function sameType(string $expected, string $actual): boolTwo SQL types that are one: the display width of an integer (tinyint(1), int(11)) is no type - MySQL 8.0.19 dropped it, and a column made before shows it still - so tinyint(1) and tinyint are the same boolean.
MySqlSchema::columnType()
public function columnType(Column $column): stringThe SQL type MySQL 8 writes for a column of the description (information_schema's COLUMN_TYPE).
MySqlSchema::enumeration()
public static function enumeration(Column $column): stringenum('A','B') of the column's values: the SQL type of an enumeration.
MySqlSchema::set()
public static function set(Column $column): stringset('A','B') of the column's values: the SQL type of a set.
Omnibridge\Schema\Declaration
Attribute class
final class Attribute Attribute.php:12
One mapping attribute as an entity carries it, read without its class: its name in the vocabulary (Column, ManyToOne, JoinColumn...) and its arguments by parameter name, as written - a positional argument named after the parameter it fills, a nested attribute (a JoinTable's join columns) an Attribute itself. get() adds the vocabulary's default of an argument left out.
public readonly string $namepublic readonly array $argumentsas written, by parameter name
Attribute::__construct()
public function __construct(public readonly string $name, public readonly array $arguments = [])$argumentsas written, by parameter name
Attribute::has()
public function has(string $argument): boolAttribute::get()
public function get(string $argument): mixedThe argument as written, else the vocabulary's default.
Attribute::all()
public function all(): array- Returns
every parameter of the attribute: as written, else its default
Attribute::toArray()
public function toArray(): arrayAttribute::fromArray()
public static function fromArray(array $data): selfAttributeReader class
final class AttributeReader implements Declarations AttributeReader.php:16
Reads an entity class's mapping attributes into its ClassDeclaration, by reflection and without instantiating them: an attribute is its name and its arguments (ReflectionAttribute::getArguments()), so its class need not exist - the ORM need not be installed to read what the entities declare.
Only the attributes of the vocabulary (Vocabulary::NAMESPACE) are read; a property or a method that carries none is left out. A constant written as an argument (UtcDateTimeImmutableType::NAME) is evaluated by PHP, so its class must load.
AttributeReader::read()
public function read(string|\ReflectionClass $class): ?ClassDeclarationThe class's declaration, null for a class that is no entity, mapped superclass nor embeddable.
ClassDeclaration class
final class ClassDeclaration ClassDeclaration.php:14
What an entity class declares of its mapping, read from its attributes and nothing else: the class's own attributes (Entity, Table, InheritanceType...), then each property in the order reflection lists them - the inherited ones among them, with the class that declares each - and each public method carrying a lifecycle attribute. Nothing is resolved here (no default name, no type guessed): that is the description's (Omnibridge\Schema\Description), and a persistence's that reads the declaration as its mapping.
public readonly string $classpublic readonly array $attributesthe class's own, in the order they are written
public readonly array $propertiesin reflection's order
public readonly array $methodsthe public ones that carry a mapping attribute, in reflection's order
ClassDeclaration::__construct()
public function __construct(public readonly string $class, public readonly array $attributes = [], public readonly array $properties = [], public readonly array $methods = [])$attributesthe class's own, in the order they are written
$propertiesin reflection's order
$methodsthe public ones that carry a mapping attribute, in reflection's order
ClassDeclaration::kind()
public function kind(): ?stringEntity, MappedSuperclass or Embeddable: what the class is, null for a class the mapping does not hold.
ClassDeclaration::attribute()
public function attribute(string $name): ?AttributeThe class attribute of that name (the last one written), null if none.
ClassDeclaration::attributes()
public function attributes(string $name): arrayClassDeclaration::property()
public function property(string $name): ?MemberClassDeclaration::toArray()
public function toArray(): arrayClassDeclaration::fromArray()
public static function fromArray(array $data): selfDeclarationSet class
final class DeclarationSet implements Declarations DeclarationSet.php:6
Declarations kept as data, by class: read back from their plain form (toArray(), a JSON file), or gathered from another source.
DeclarationSet::__construct()
public function __construct(iterable $declarations = [])DeclarationSet::of()
public static function of(Declarations $declarations, iterable $classes): selfThe declarations of these classes, as a reader reads them.
@param iterable<string> $classes
DeclarationSet::read()
public function read(string|\ReflectionClass $class): ?ClassDeclarationDeclarationSet::all()
public function all(): arrayDeclarationSet::toArray()
public function toArray(): arrayDeclarationSet::fromArray()
public static function fromArray(array $data): selfDeclarations interface
interface Declarations Declarations.php:12
Where the declarations of the entity classes come from: their attributes (AttributeReader), or a set kept as data (DeclarationSet: a file written once, another vocabulary turned into this one). A persistence bridge maps the classes from it - omnibridge/doctrine's DeclarationDriver gives Doctrine its metadata from it - and never reads the classes' attributes itself.
Declarations::read()
public function read(string|\ReflectionClass $class): ?ClassDeclarationThe class's declaration, null for a class it does not map.
Member class
final class Member Member.php:6
A property or a method of an entity class with the mapping attributes it carries, and the class that declares it.
public readonly string $namepublic readonly string $classpublic readonly array $attributesin the order they are written
Member::__construct()
public function __construct(public readonly string $name, public readonly string $class, public readonly array $attributes = [])$attributesin the order they are written
Member::attribute()
public function attribute(string $name): ?AttributeThe attribute of that name (the last one written, as a non-repeatable attribute is read), null if none.
Member::attributes()
public function attributes(string $name): array- Returns
every attribute of that name (a repeatable one), in order
Member::toArray()
public function toArray(): arrayMember::fromArray()
public static function fromArray(array $data): selfVocabulary class
final class Vocabulary Vocabulary.php:17
The mapping attributes the entities are written with - those of the Doctrine\ORM\Mapping namespace, the vocabulary omnibase's entities and their applications' carry - as plain data: each attribute's parameters in the order of its constructor, with their defaults, and whether it may be written more than once. With it a declaration is read without the attributes' classes (a positional argument gets its parameter's name, a left-out one its default), so without the ORM installed.
Kept equal to doctrine/orm 3's constructors: omnibridge/doctrine's VocabularyTest compares the two, parameter by parameter.
const NAMESPACE = 'Doctrine\ORM\Mapping\\'The namespace whose attributes are read.
const PARAMETERS = ['AssociationOverride' => ['name' => self::REQUIRED, 'joinColumns' => null, 'inverseJoinColumns' => null, 'joinTable' => null, 'inversedBy' => null, 'fetch' …const REPEATABLE = ['Index', 'InverseJoinColumn', 'JoinColumn', 'UniqueConstraint']The attributes that may be written more than once on the same class or property.
const CALLBACKS = ['PrePersist' => 'prePersist', 'PostPersist' => 'postPersist', 'PreUpdate' => 'preUpdate', 'PostUpdate' => 'postUpdate', 'PreRemove' => 'preRemove', 'PostRem…The lifecycle attributes of a method, by the event they name.
const REQUIRED = "\x00required"The default of a required parameter: there is none.
Vocabulary::nameOf()
public static function nameOf(string $className): ?stringThe attribute's name in the vocabulary of a class name (Doctrine\ORM\Mapping\Column: Column), null outside it.
Vocabulary::parameters()
public static function parameters(string $name): array- Returns
the attribute's parameters, in its constructor's order
Vocabulary::defaults()
public static function defaults(string $name): array- Returns
the attribute's optional parameters and their defaults
Vocabulary::defaultOf()
public static function defaultOf(string $name, string $parameter): mixedVocabulary::isRepeatable()
public static function isRepeatable(string $name): bool