Read from the package's own PHP files at the commit a6cd864fe03d: 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.
CascadesclassWhat an association carries along, as its declaration says (the mapping attribute's `cascade` and `orphanRemoval`, read by omnisense/omnibridge's declaration reader, no ORM loaded): which operations of the unit of work go on to the associated entities (persist, remove; refresh, detach and merge are Doctrine's own), and whether an entity taken out of the association is deleted (orphan removal).
4 methods
CastsclassA column's value as the entity holds it, and back: the conversions Doctrine's DBAL types make, by the type's name a description gives (Omnibridge\Schema\Field::$type), without DBAL.
7 methods
CommitOrderclassThe order a flush writes entities in, as Doctrine's commit order computes it (its TopologicalSort): an entity after those it depends upon - the new entities its owning to-one associations point to, for the inserts; for the deletes, an entity before those it points to -, a depth-first walk in the order the nodes were added, so that two backends given the same work write the same rows in the same order (and the database gives the same identifiers).
4 methods
ConnectionsclassEloquent's database connection, with a framework or without one: the store (EntityStore) reads through an Illuminate\Database\Connection, whoever made it.
5 methods
Containerclassomnibridge/eloquent's services declared as data, for omnisense/omnibridge's Omnibridge\Container (plan "omnibase agnostic", step F7d: the persistence in plain PHP), which adds them when it runs on Eloquent (Persistence\Persistences: the parameter `persistence`, or Eloquent the only persistence installed).
2 methods
EloquentUnitOfWorkclassomnisense/omnibridge's unit of work on the store, writing as Doctrine's unit of work writes (plan "omnibase agnostic", step F7c), so that the same entities given the same calls leave the same rows on both backends.
35 methods
EntityMapclassWhere an entity's values are, read from its description: the tables of its class, each field's and each owning association's table and column, its identifier, and how a row says which class it is.
12 methods · 6 properties
EntityNotFoundclassA lazy entity (a reference, an association's ghost) whose row is not there when it is first used - deleted since, or left out by a scope -, as Doctrine's EntityNotFoundException says it of a proxy.
1 method
EntityStoreclassThe data mapper: rows of Eloquent's connection read into the application's plain PHP entities, as a description maps them (Omnibridge\Schema), with no Eloquent model - the entities are those Doctrine maps, and nothing in them knows which backend read them.
33 methods
IdentityMapclassOne object per row: the entities a store read (or referenced), by their root class and identifier, so that a row read twice - by id, through an association, in a finder's result - is the same object, as Doctrine's unit of work keeps it.
9 methods
InvalidPersistenceclassA write the unit of work refuses because the entities asked for it wrongly, where Doctrine's unit of work refuses it too (its ORMInvalidArgumentException): a new entity reached through an association that does not cascade the persist, a cycle of mandatory foreign keys, an entity of no described class.
5 methods
LazyCollectionclassA to-many association read when it is first used: doctrine/collections' Collection, which the entities type their associations on (ArrayCollection when they make them, Doctrine's PersistentCollection when Doctrine reads them), loaded by the store on the first call that needs its elements.
16 methods
MappingclassThe tables of every entity a description holds (EntityMap per class), the class asked by any of its names: an entity's own, or a class alias of it (omnibase's App\Entity\X for Base\Entity\X where the application has none).
4 methods · 1 property
PersisterclassThe statements of a flush, as Doctrine's entity and collection persisters write them, through Eloquent's query builder: each column a change set gives, by the table that holds it (EntityMap).
7 methods
UnsupportedPersistenceclassWhat omnibridge/eloquent's unit of work does not do, refused aloud rather than done wrong (omnisense/omnibase's plan "omnibase agnostic", step F7c): an identifier the database cannot give it (a sequence, a custom generator), a composite identifier or join column, a unit of work closed by a failed flush.
4 methods
AttributeRelayclassomnibase's behaviour attributes on omnibridge/eloquent's unit of work (plan "omnibase agnostic", step F7c): what omnibridge/doctrine's AttributeSubscriber does on Doctrine's events, on the Lifecycle events the unit of work dispatches at the same moments - a listener of it (EloquentUnitOfWork::listen()).
4 methods
EloquentBackendclassomnisense/omnibridge's Backend on omnibridge/eloquent (plan "omnibase agnostic", step F7b): the name "eloquent", what it can do (lazy associations: ghosts and lazy collections; no second-level or result cache; transactions, with the writes since F7c), its unit of work, and omnibase's scopes - the trash and the vault - added to every query of the store while they are enabled, as Doctrine's TrashFilter and VaultFilter are: a scope's criteria (Scope::criteria()) on the entity's columns, `deletedAt IS NULL`, `vault IS NULL OR vault = :environment` - in the class's own query, and in the ON of a join of it (the finder's), as Doctrine puts its filters there.
7 methods
EloquentBehavioursclassThe behaviours' parts on omnibridge/eloquent (plan "omnibase agnostic", step F7c), registered for EloquentUnitOfWork with omnisense/omnibase's Backends where omnibridge/doctrine's DoctrineBehaviours registers Doctrine's: #[Vault]'s forced update, #[Slugify]'s pending writes and unique index, #[Cache]'s eviction (no second-level cache), the #[OrderColumn]'s lazy order; the entities' shapes (the store's description); what the core's services ask beyond the unit of work (row locks, conditional updates, the entity cache, deletes by criteria); the column types holding arrays; the backend and its scopes; the repositories (the persistence's own, EloquentPersistence's).
4 methods · 1 constant
EloquentEntitiesclassomnibase's repository on the store (plan "omnibase agnostic", step F7b): the core's Entities - find(), findAll(), findBy(), findOneBy(), count() - and the finder language (findBySlug(), cacheOneByStateAndSlugStartingWith(), countForParentByState()...), both compiled by EloquentFinder on Illuminate's query builder as omnibridge/doctrine's ServiceEntityRepository compiles them on Doctrine: findBy()'s criteria array reads the words a name would (a list IN, a Key without a join, a Group in parentheses, an association joined), its order the finder's (a path, FIELD(), RAND()). A finder that hands back Doctrine's Query hands back a FinderQuery (getResult(), getOneOrNullResult()).
16 methods
EloquentPersistenceclassomnibase's entities on an Eloquent connection, in one call (plan "omnibase agnostic", step F7b): the description of the core's and the application's entities (EntitySchema, no other persistence asked), the store reading them with omnibase's column types (OmnibaseCasts), the unit of work, the backend and its scopes, the repositories.
9 methods · 1 constant
EloquentRepositoriesclassomnibase's Repositories on the store (plan "omnibase agnostic", step F7b): the repository of an entity - the core's on Eloquent (Repository\*, each implementing the core's interface: Threads, Users, Comments...) for its entity and the entity's subclasses (App\Entity\Article\Article gets ThreadRepository's), an application's own where one is registered (register()), EloquentEntities for any other class (find, findBy, count and the finder language) -, and the entities of identifiers: one query for those not read yet, the identity map for the others.
7 methods · 1 constant
OmnibaseCascadesclassomnibase's own cascade declarations on Eloquent (plan "omnibase agnostic", step F7c): #[Cascade(value: [...])] and #[OrphanRemoval] on an association's property, or on its class with the property named (`column`), which on Doctrine rewrite the association's mapping when its metadata is loaded (their loadClassMetadata()). Read here from the attributes' arguments, nothing instantiated: what Cascades::extend() takes. And the translations' association, which omnibridge/doctrine's IntlSubscriber maps (step F7c).
1 method
OmnibaseCastsclassomnibase's column types read as omnibridge/doctrine's DBAL types read them (plan "omnibase agnostic", step F7b):
1 method
Omnibridge\Eloquent\Omnibase\Behaviour
EloquentBulkDeletesclassBulkDeletes on omnibridge/eloquent (plan "omnibase agnostic", step F7c): the rows of a class whose fields equal the criteria deleted in statements, no entity read nor event dispatched - DoctrineBulkDeletes' DQL DELETE: the class's rows only (a single-table class by its discriminator), the store's scopes applied (Doctrine's filters), and for a joined hierarchy every table of it, the subclasses' first (Doctrine's multi-table delete). The number of rows.
3 methods
EloquentCacheBackendclass#[Cache]'s part on omnibridge/eloquent (plan "omnibase agnostic", step F7c): the store keeps no second-level cache, so nothing is evicted. What DoctrineCacheBackend does whether a cache is configured or not stays: for the entity itself, each association whose target is cached is read through its getter first (a lazy one is loaded), so that the entity is in the same state on both backends when its row is written.
2 methods
EloquentColumnTypesclassColumnTypes on omnibridge/eloquent (plan "omnibase agnostic", step F7c): a field holds a PHP array when its type is `json` or a set enumeration (the store's casts know the core's and the application's, OmnibaseCasts) - what DoctrineColumnTypes answers from Doctrine's types.
2 methods
EloquentConditionalUpdatesclassConditionalUpdates on omnibridge/eloquent (plan "omnibase agnostic", step F7c): the field's column set to a new value where it still holds the old one, in one statement (DoctrineConditionalUpdates' DQL UPDATE); true when the row was.
2 methods
EloquentEntityCacheclassEntityCache on omnibridge/eloquent (plan "omnibase agnostic", step F7c): the store keeps no second-level cache.
4 methods
EloquentOrderColumnBackendclass#[OrderColumn]'s part on omnibridge/eloquent (plan "omnibase agnostic", step F7c): a to-many association the store reads lazily is ordered by the stored positions without being read now - its elements are held, once it is read, in omnibase's OrderedArrayCollection, which sorts itself on its first use (what DoctrineOrderColumnBackend does inside Doctrine's PersistentCollection); one read already is wrapped the same way, its entries kept.
2 methods
EloquentRowLocksclassRowLocks on omnibridge/eloquent (plan "omnibase agnostic", step F7c): the work run in a transaction holding the entity's row (SELECT ... FOR UPDATE, as Doctrine's PESSIMISTIC_WRITE lock reads it; SQLite has no row lock, its transaction is the lock).
2 methods
EloquentSlugifyBackendclass#[Slugify]'s part on omnibridge/eloquent (plan "omnibase agnostic", step F7c): the writes of the running flush - its insertions, then its updates, in the order the unit of work scheduled them, as DoctrineSlugifyBackend lists Doctrine's -, and whether the database still holds a unique index on the slug's column alone (read from the database's indexes through Illuminate's schema builder, once per process and column).
3 methods
EloquentVaultBackendclass#[Vault]'s part on omnibridge/eloquent (plan "omnibase agnostic", step F7c): a secured field given a new plain value is written again, the entity scheduled for an update whatever its change set says - Doctrine's scheduleForUpdate().
2 methods
Omnibridge\Eloquent\Omnibase\Finder
EloquentFinderclassomnibase's finder language on Illuminate's query builder (plan "omnibase agnostic", step F7b): the core's Finder\Parser reads a finder's name and arguments (read()), this class compiles the Query into the store's query of the class and runs it (execute()) - what omnibridge/doctrine's ServiceEntityParser does on Doctrine, word for word, so that one name gives the same rows on both persistences (FinderParityTest):
6 methods
EntitySubjectclassWhat omnibase's finder language asks of an entity (Base\Database\Repository\Finder\Subject), answered from its description (plan "omnibase agnostic", step F7b): its class, its fields and associations, the names a criterion may give them - its aliases (#[Alias]), a field by its column, as omnibridge/doctrine's ClassMetadataManipulator:: getFieldNames() reads them from Doctrine's metadata -, and a Query-by-Example's criteria (the set fields and to-one associations of the object given, as ServiceEntityRepository::criteriaFromSelect() reads them).
11 methods
FinderQueryclassWhat a finder hands back where omnibridge/doctrine hands back Doctrine's Query (findBy...(), findAll(), findLast...(), findAtMost...(), findPrevious...(), findNext...(), findRandomly...()): the compiled query, run when its result is asked - getResult(), getOneOrNullResult() -, as often as it is asked.
11 methods
Omnibridge\Eloquent\Omnibase\Lifecycle
DemoAccountLockListenerclassA demonstration account kept as declared, on omnibridge/eloquent (plan "omnibase agnostic", step F7c): omnibridge/doctrine's DemoAccountLockSubscriber, the rule the core's (DemoAccountLock). During a request, at PreFlush: a declared account's deletion refused, and each declared account the unit of work holds given back its identifier, address, password and second factor (the values read and written as the store holds them), the visitor told once.
3 methods
EloquentObjectManagerclassdoctrine/persistence's ObjectManager over omnibridge/eloquent's unit of work (plan "omnibase agnostic", step F7c): what the lifecycle arguments of omnibase's entity dispatchers carry (their subclasses type their hooks on Doctrine\Persistence\Event\LifecycleEventArgs: lesringostars' NewsletterEventDispatcher). The unit of work's operations; Doctrine's metadata and repositories are refused aloud (there are none: the description and omnisense/omnibase's Repositories stand in their place).
15 methods
EntityDispatcherListenerclassomnibase's entity dispatchers on omnibridge/eloquent (plan "omnibase agnostic", step F7c): an AbstractEventDispatcher (the user.* and thread.* events, an application's own: lesringostars' newsletter.*) called at the moments Doctrine calls it - before a write it notes its events, after it dispatches them.
4 methods
EntityDispatchersListenerclassA host's entity dispatchers on omnibridge/eloquent (plan "omnibase agnostic", step F7d): the services its container makes (Symfony's tagged base.entity_dispatcher, Laravel's, Omnibridge\Container's), on the unit of work the container gives - this persistence's -, read at the first entity event, since they are made with it. Each is then called as EntityDispatcherListener calls one, in their order. They are the container's, not made here: their life is the container's, the one this persistence lives in, so the host's flush of what they left pending (flushPending(), AbstractEventDispatcher::live()) never reaches a unit of work another persistence holds.
4 methods
IntlListenerclassomnibase's translations on omnibridge/eloquent (plan "omnibase agnostic", step F7c): what omnibridge/doctrine's IntlSubscriber does at the flush and the reads (its mapping part - the translations' association, cascades, unique locale - is the description's and OmnibaseCascades' here; its query part, TranslatableWalker, the finder's join).
1 method
OmnibaseListenersclassomnibase's lifecycle on omnibridge/eloquent's unit of work, in one call (plan "omnibase agnostic", step F7c): the behaviours' relay and the adapters of the listeners omnibridge/doctrine and omnibase register on Doctrine's events, listening in Doctrine's order (by priority, then as they are declared: AttributeSubscriber and IntlSubscriber 2048, TrasheableSubscriber 1024, VersionableSubscriber 512, then ThreadSubscriber, SettingSubscriber, TextOverrideCacheListener, the entity dispatchers, UserSubscriber's and DemoAccountLockSubscriber's preFlush).
3 methods
PreFlushListenerclassA service's preFlush() called as each flush begins, on omnibridge/eloquent (plan "omnibase agnostic", step F7c): omnisense/omnibase's UserSubscriber, whose preFlush() takes no Doctrine argument (the tokens it revokes).
2 methods
PreUpdateArgsclassdoctrine/persistence's lifecycle arguments of a PreUpdate, with its changes (getEntityChangeSet(), as Doctrine's PreUpdateEventArgs gives them): omnisense/omnibase's EntityHydrator reads the values they replace from them.
2 methods
SettingListenerclassThe settings' snapshot kept in step on omnibridge/eloquent (plan "omnibase agnostic", step F7c): omnibridge/doctrine's SettingSubscriber, the rule the core's (SettingsInvalidation): a Setting or SettingIntl written empties it.
2 methods
StoreMentioneesclassThe host's mention enhancer, its mentionees given as the store holds them (plan "omnibase agnostic", step F7c): the enhancer finds the users a text mentions through the host's repositories, which may be another persistence's (a site still on Doctrine beside the store, F7c's proofs); a Mention written by the unit of work must point to the store's user, so each one is read again from the store by its identifier. Everything else is the enhancer's.
5 methods
TextOverrideListenerclassThe translations' overrides kept in step on omnibridge/eloquent (plan "omnibase agnostic", step F7c): what omnibase's TextOverrideCacheListener does on Doctrine's events - a TextOverride written, the overriding translator's cache emptied once the flush is done.
2 methods
ThreadListenerclassA thread's participants on omnibridge/eloquent (plan "omnibase agnostic", step F7c): omnisense/omnibase's ThreadSubscriber's Doctrine hooks, the rule the core's (ThreadParticipants). A new reply followed by its parent's owners (PrePersist); at OnFlush, the mentions of every thread whose text the flush writes or that it makes publishable, and the followers of a reply moved under another parent (its change set computed again with its collections).
2 methods
TrasheableListenerclassomnibase's soft delete on omnibridge/eloquent (plan "omnibase agnostic", step F7c): omnibridge/doctrine's TrasheableSubscriber, on the unit of work's OnFlush, the rule the core's (TrashRecorder).
2 methods
VersionableListenerclassomnibase's revisions on omnibridge/eloquent (plan "omnibase agnostic", step F7c): omnibridge/doctrine's VersionableSubscriber, the rule the core's (RevisionRecorder). At OnFlush, each #[Versionable] entity the flush updates, or whose collection it finds changed, gives its anchor (the entity itself, or the translatable of a translation) one Revision of what changed - its versioned fields' changes and its versioned collections' elements before and after -, inserted in the same flush. After the flush, the revisions beyond the most recent ones kept (base.extension.max_revisions) are deleted, in statements.
2 methods
Omnibridge\Eloquent\Omnibase\Repository
ThreadIntlRepositoryclassomnibridge/doctrine's ThreadIntlRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
1 method
ThreadRepositoryclassomnibridge/doctrine's ThreadRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder. getHierarchy() reads the class's #[Hierarchify] (its own, else its nearest parent's).
18 methods
UserRepositoryclassomnibridge/doctrine's UserRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder. Security's user loader, user provider and password upgrader too (step F7d), as Doctrine's declares them through Base\Contract\SecurityUserLoader and SecurityUserProvider (Symfony's interfaces where its security and doctrine-bridge are installed, empty ones elsewhere): what omnibridge/symfony's UserProvider and the entity user provider of a site's security.yaml ask, the same answers; the password written by the unit of work's flush.
14 methods
Omnibridge\Eloquent\Omnibase\Repository\Analytics
PageViewRepositoryclassomnibridge/doctrine's Analytics\PageViewRepository on Eloquent: countViews() and earliestDate() are finders (sumOf, minOf), compiled by EloquentFinder (step F7b); the upsert and the breakdowns, declared #[BackendOnly] on the interface (no finder: each persistence writes them), are omnibridge/doctrine's SQL sent through Eloquent's connection (step F7f) - ON DUPLICATE KEY UPDATE on MySQL, ON CONFLICT elsewhere, SUM() grouped by DATE() or the hour.
7 methods
PageVisitRepositoryclassomnibridge/doctrine's Analytics\PageVisitRepository on Eloquent (step F7f): its four methods, declared #[BackendOnly] on the interface (no finder: each persistence writes them), are omnibridge/doctrine's SQL sent through Eloquent's connection - INSERT IGNORE (ON CONFLICT DO NOTHING off MySQL), COUNT(*) over a DISTINCT subquery, grouped by DATE() or the hour. The plain reads (find, findBy, count, the finders) are EloquentEntities'.
4 methods
VisitRepositoryclassomnibridge/doctrine's Analytics\VisitRepository on Eloquent: countUnique() is a finder (distinctCountFor...), compiled by EloquentFinder (step F7b); the INSERT IGNORE, the retention and the breakdowns, declared #[BackendOnly] on the interface (no finder: each persistence writes them), are omnibridge/doctrine's SQL sent through Eloquent's connection (step F7f).
6 methods
Omnibridge\Eloquent\Omnibase\Repository\Extension
RevisionRepositoryclassomnibridge/doctrine's Extension\RevisionRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
2 methods
TrashBallRepositoryclassomnibridge/doctrine's Extension\TrashBallRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
4 methods
Omnibridge\Eloquent\Omnibase\Repository\Hours
ScopedWeekRepositoryclassomnibridge/doctrine's Hours\ScopedWeekRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder, the writes through the unit of work (step F7c).
4 methods
SpecialDayRepositoryclassomnibridge/doctrine's Hours\SpecialDayRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
1 method
WeekDayHoursRepositoryclassomnibridge/doctrine's Hours\WeekDayHoursRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder, the writes through the unit of work (step F7c).
2 methods
Omnibridge\Eloquent\Omnibase\Repository\Layout
ImageCropRepositoryclassomnibridge/doctrine's Layout\ImageCropRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
3 methods
RedirectionRepositoryclassomnibridge/doctrine's Layout\RedirectionRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder; hit(), declared #[BackendOnly] on the interface (no finder), one UPDATE on Eloquent's connection (F7f).
2 methods
SemanticRepositoryclassomnibridge/doctrine's Layout\SemanticRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
1 method
SettingRepositoryclassomnibridge/doctrine's Layout\SettingRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
2 methods
TextOverrideRepositoryclassomnibridge/doctrine's Layout\TextOverrideRepository on Eloquent (plan "omnibase agnostic", step F7b): no interface of the core's names it, but omnibase's OverridingTranslator calls its map().
1 method
WidgetRepositoryclassomnibridge/doctrine's Layout\WidgetRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
2 methods
Omnibridge\Eloquent\Omnibase\Repository\Layout\Widget
SlotRepositoryclassomnibridge/doctrine's Layout\Widget\SlotRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
1 method
Omnibridge\Eloquent\Omnibase\Repository\Thread
CommentRepositoryclassomnibridge/doctrine's Thread\CommentRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
5 methods
LikeRepositoryclassomnibridge/doctrine's Thread\LikeRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
1 method
MentionRepositoryclassomnibridge/doctrine's Thread\MentionRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
1 method
TagRepositoryclassomnibridge/doctrine's Thread\TagRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
4 methods
Omnibridge\Eloquent\Omnibase\Repository\User
ComplaintRepositoryclassomnibridge/doctrine's User\ComplaintRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
1 method
ConnectionRepositoryclassomnibridge/doctrine's User\ConnectionRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
2 methods
IdentityRepositoryclassomnibridge/doctrine's User\IdentityRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
2 methods
NotificationRepositoryclassomnibridge/doctrine's User\NotificationRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
2 methods
PasskeyRepositoryclassThe passkeys on the store (plan "omnibase agnostic", steps F7b and F7c): the core's Passkeys, and PasskeyRecords - webauthn-symfony-bundle's credential repository where it is installed (CredentialRecordRepositoryInterface and CanSaveCredentialRecord), an interface that asks nothing elsewhere - as omnibridge/doctrine's PasskeyRepository answers them: a credential found by its identifier, a user's credentials, a credential saved through the unit of work (the passkey's counters updated, or a new passkey of the user its handle names).
6 methods
PushSubscriptionRepositoryclassomnibridge/doctrine's User\PushSubscriptionRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
1 method
TokenRepositoryclassomnibridge/doctrine's User\TokenRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
4 methods
Omnibridge\Eloquent
Cascades class
final class Cascades Cascades.php:18
What an association carries along, as its declaration says (the mapping attribute's cascade and
orphanRemoval, read by omnisense/omnibridge's declaration reader, no ORM loaded): which operations of the
unit of work go on to the associated entities (persist, remove; refresh, detach and merge are Doctrine's own),
and whether an entity taken out of the association is deleted (orphan removal).
The description of the tables does not carry them (they change no table); an application whose own attributes add some (omnibase's #[Cascade] and #[OrphanRemoval]) gives a resolver (extend()).
Cascades::__construct()
public function __construct(readonly Declarations $declarations = new AttributeReader())Cascades::extend()
public function extend(\Closure $resolver): voidA resolver of an application's own declarations: given the entity's class, the association's property, and what its mapping attribute says, it answers [cascade, orphanRemoval].
Cascades::cascades()
public function cascades(string $class, Relation $relation, string $operation): boolWhether the operation ("persist", "remove", "refresh"...) goes on to the association's entities. Orphan removal on a one-to-many or one-to-one association implies the removal's cascade, as Doctrine completes such a mapping (isCascadeRemove): the owner removed, its entities go with it - User::$connections (orphanRemoval, no cascade) left its userConnection rows, and the user's own delete failed on their foreign key.
Cascades::orphanRemoval()
public function orphanRemoval(string $class, Relation $relation): boolWhether an entity taken out of the association (or replaced in it) is deleted.
Casts class
final class Casts Casts.php:27
A column's value as the entity holds it, and back: the conversions Doctrine's DBAL types make, by the type's name a description gives (Omnibridge\Schema\Field::$type), without DBAL.
- the portable types: integer, smallint and bigint (an int, a bigint past PHP_INT_MAX a string), boolean, float, decimal (a string), string, text, ascii_string and guid, json (decoded to arrays), simple_array (NULL read as [] as DBAL reads it), the dates (datetime, datetimetz, date, time and their _immutable, in PHP's default zone as DBAL reads them), binary and blob (kept as they come);
- utc(): datetime and datetimetz read and written in UTC, and utc_datetime, utc_datetime_immutable - omnibridge/doctrine's Types::register(), which omnibase sites run on;
- an application's own types: a conversion given by name (with()), else what its ColumnTypes say - an alias followed to its portable type, an enumeration's value as the string it is, a set's values as a list.
A type nothing knows is refused, never read as a raw string silently.
Casts::__construct()
public function __construct(readonly ?ColumnTypes $columnTypes = null, readonly bool $utc = false)Casts::utc()
public static function utc(?ColumnTypes $columnTypes = null): selfThe conversions of an omnibase site: datetime and datetimetz in UTC, the utc_ types (omnibridge/doctrine's Types::register()).
Casts::with()
public function with(string $type, \Closure $toPhp, ?\Closure $toDatabase = null, bool $readsNull = false): selfThe same conversions, plus a type of the application's own (or one replaced).
$toPhpthe column's value (never null) => the entity's
$toDatabasethe entity's value (never null) => the column's; the value as it is without
$readsNullwhether $toPhp is given null too (a set reads NULL as no value: [])
Casts::columnTypes()
public function columnTypes(): ?ColumnTypesCasts::knows()
public function knows(string $type): boolWhether a column of that type is read as something else than it comes (a date, a decoded array...).
Casts::toPhp()
public function toPhp(string $type, mixed $value): mixedThe column's value as the entity holds it.
Casts::toDatabase()
public function toDatabase(string $type, mixed $value): mixedThe entity's value as the column keeps it: what a criterion binds.
CommitOrder class
final class CommitOrder CommitOrder.php:16
The order a flush writes entities in, as Doctrine's commit order computes it (its TopologicalSort): an entity after those it depends upon - the new entities its owning to-one associations point to, for the inserts; for the deletes, an entity before those it points to -, a depth-first walk in the order the nodes were added, so that two backends given the same work write the same rows in the same order (and the database gives the same identifiers).
An optional edge (a nullable foreign key) in a cycle is the one broken, the closest one backtracking: that entity is inserted with NULL there and updated once the other has its row (an extra update). A cycle of mandatory edges cannot be written: refused (InvalidPersistence::cycle()).
CommitOrder::add()
public function add(object $node): voidCommitOrder::has()
public function has(object $node): boolCommitOrder::depends()
public function depends(object $from, object $to, bool $optional): void$from depends upon $to: $to comes first. A mandatory edge is never made optional again.
CommitOrder::sort()
public function sort(): arrayConnections class
final class Connections Connections.php:23
Eloquent's database connection, with a framework or without one: the store (EntityStore) reads through an Illuminate\Database\Connection, whoever made it.
- inside Laravel, the application's own connection (laravel():
app('db'), a connection's name or the default one); - outside Laravel, Capsule (capsule(): Illuminate's configuration array; url(): a DATABASE_URL as Doctrine and Symfony write it);
- beside another persistence, its PDO (pdo()): the same connection, so the same transaction - what a comparison of two backends on one database needs.
Connections::capsule()
public static function capsule(array $config, string $name = 'default'): ConnectionA connection made by Capsule, Eloquent's manager outside Laravel.
$configIlluminate's configuration of a connection (driver, host, database, username...)
Connections::url()
public static function url(string $url, string $name = 'default'): ConnectionA connection made by Capsule from a database URL: mysql://user:password@host:3306/name?charset=utf8mb4, sqlite:///path/to/file.db (sqlite:///:memory: in memory), pgsql://... The query string's keys are added to the configuration (charset, collation, serverVersion is ignored).
Connections::config()
public static function config(string $url): arrayThe configuration array of a database URL (url()).
Connections::pdo()
public static function pdo(\PDO $pdo, string $database = ''): ConnectionA connection on a PDO that is already open - Doctrine's ($connection->getNativeConnection()), a test's: the
same database and the same transaction as whoever opened it.
Connections::laravel()
public static function laravel(ConnectionResolverInterface $database, ?string $name = null): ConnectionThe connection of a Laravel application: its database manager (app('db')), the connection named or the
default one.
Container class
final class Container Container.php:22
omnibridge/eloquent's services declared as data, for omnisense/omnibridge's Omnibridge\Container (plan "omnibase
agnostic", step F7d: the persistence in plain PHP), which adds them when it runs on Eloquent
(Persistence\Persistences: the parameter persistence, or Eloquent the only persistence installed).
With omnisense/omnibase: its persistence (EloquentPersistence::fromContainer(): Capsule on database.url or
DATABASE_URL unless the container gives a connection, omnibase's lifecycle on the container's services), its unit
of work as UnitOfWork and Snapshots, its backend as Backend, its repositories as Repositories, and each repository
interface of the core (Base\Discovery's repositories) answered by the repository implementing it. Without the core,
nothing: the store needs a description, which the application builds (EntityStore, EloquentUnitOfWork).
Symfony and Laravel wire the same pieces from their own configuration (omnibridge/symfony, omnibridge/laravel).
Container::definitions()
public static function definitions(): array- Returns
Omnibridge\Container\Declarations' format
Container::interfaces()
public static function interfaces(): arrayThe core's repository interfaces a repository answers (Repositories itself aside), each with the entity it reads when it is the application's: Users the application's users (App\Entity\User, as the core's alias names App\Repository\UserRepository), the others their own entity (null).
EloquentUnitOfWork class
final class EloquentUnitOfWork implements UnitOfWork, Snapshots EloquentUnitOfWork.php:46
omnisense/omnibridge's unit of work on the store, writing as Doctrine's unit of work writes (plan "omnibase agnostic", step F7c), so that the same entities given the same calls leave the same rows on both backends.
- persist(): a new entity scheduled for insertion (PrePersist), and the entities its associations reach where they cascade the persist; remove(): the entities its associations cascade the removal to first, then the entity scheduled for deletion (PreRemove); persisting a removed entity takes it back.
- flush(), in Doctrine's order (its UnitOfWork::commit()):
1. PreFlush;
2. the change sets: each new entity's fields and owning to-one associations; each managed entity's values
compared with what it held when read or last flushed (the store's snapshot), strictly (
!==, an object by identity); new entities reached through an association persisted when it cascades (a PrePersist each), refused otherwise (InvalidPersistence::notCascaded()); the owning many-to-many collections compared with their snapshot (a managed owner with no other change is updated with an empty change set, as Doctrine does); the entities taken out of an orphan-removing association removed; 3. OnFlush (a listener may persist, remove, change and recompute); 4. in one transaction: the inserts in commit order (CommitOrder: an entity after the new entities its foreign keys point to; a nullable one in a cycle written NULL then updated), each identifier the database gives set on its entity, then PostPersist for each; the updates by class and identifier, each after its PreUpdate (whose setNewValue() values are written, and whose listeners' direct changes are recomputed, as Doctrine recomputes after preUpdate), then PostUpdate; the extra updates; the join tables' rows; the deletes in reverse dependency order, then PostRemove for each; 5. the snapshots taken again (a collection the application made becomes a LazyCollection, as Doctrine puts a PersistentCollection in its place), the removed entities taken out of the collections; PostFlush. A flush that fails is rolled back and closes the unit of work, as Doctrine closes its entity manager. - PostLoad for each entity the store reads, once the read is done.
- The events are omnisense/omnibridge's Lifecycle events, given to the listeners (listen()) and to a PSR-14 dispatcher: the behaviours of an application (omnibase's attributes) run on them, whichever backend writes.
- transactional(): the work, then a flush, in one transaction.
- Snapshots::original(): the store's snapshot.
What is not done is refused aloud (UnsupportedPersistence): an identifier generated otherwise than by the database or the application, a composite identifier or join column.
EloquentUnitOfWork::__construct()
public function __construct(readonly EntityStore $store, readonly ?EventDispatcherInterface $dispatcher = null, ?Cascades $cascades = null)EloquentUnitOfWork::store()
public function store(): EntityStoreEloquentUnitOfWork::cascades()
public function cascades(): CascadesEloquentUnitOfWork::listen()
public function listen(\Closure $listener): voidA listener of the Lifecycle events (PrePersist ... PostFlush, PostLoad), called before the PSR-14 dispatcher.
EloquentUnitOfWork::persist()
public function persist(object $entity): voidEloquentUnitOfWork::remove()
public function remove(object $entity): voidEloquentUnitOfWork::flush()
public function flush(): voidEloquentUnitOfWork::refresh()
public function refresh(object $entity): voidEloquentUnitOfWork::contains()
public function contains(object $entity): boolEloquentUnitOfWork::reference()
public function reference(string $class, mixed $id): objectEloquentUnitOfWork::transactional()
public function transactional(callable $work): mixedEloquentUnitOfWork::isNew()
public function isNew(object $entity): boolEloquentUnitOfWork::identifier()
public function identifier(object $entity): mixedEloquentUnitOfWork::className()
public function className(object $entity): stringEloquentUnitOfWork::original()
public function original(object $entity): arrayEloquentUnitOfWork::changes()
public function changes(object $entity): arrayEloquentUnitOfWork::recompute()
public function recompute(object $entity): voidDoctrine's recomputeSingleEntityChangeSet(): the entity's fields and owning to-one associations compared again with what they were when its change set was computed, the changes found added (they prevail). A new entity persisted during the flush whose change set was not computed yet gets its first one.
EloquentUnitOfWork::isScheduledForInsert()
public function isScheduledForInsert(object $entity): boolWhether the entity is scheduled for insertion (persisted, not flushed).
EloquentUnitOfWork::isScheduledForDelete()
public function isScheduledForDelete(object $entity): boolWhether the entity is scheduled for deletion (removed, not flushed).
EloquentUnitOfWork::scheduledInsertions()
public function scheduledInsertions(): array- Returns
the entities the running flush inserts
EloquentUnitOfWork::scheduledUpdates()
public function scheduledUpdates(): array- Returns
the entities the running flush updates
EloquentUnitOfWork::scheduledDeletions()
public function scheduledDeletions(): array- Returns
the entities the running flush deletes
EloquentUnitOfWork::scheduleExtraUpdate()
public function scheduleExtraUpdate(object $entity, array $changeSet): voidAn update written after the others (Doctrine's scheduleExtraUpdate()): the columns of the change set, with no PreUpdate nor PostUpdate - what a listener of OnFlush writes beside the flush (a stamp on an entity whose deletion it cancels).
EloquentUnitOfWork::scheduleForUpdate()
public function scheduleForUpdate(object $entity): voidThe entity updated by this flush whatever its change set says (Doctrine's scheduleForUpdate()): its PreUpdate and PostUpdate dispatched, its row written when a listener changed it - what #[Vault] asks at PreFlush for a secured field given its plain value again. A managed entity only.
EloquentUnitOfWork::scheduleForDelete()
public function scheduleForDelete(object $entity): voidThe entity deleted by this flush, no PreRemove dispatched and nothing cascaded (Doctrine's scheduleForDelete()): what a listener of the flush asks for an entity it found empty (an empty translation).
EloquentUnitOfWork::propertyChanged()
public function propertyChanged(object $entity, string $property, mixed $before, mixed $after): voidA property's change told by a listener (Doctrine's propertyChanged()): in the entity's change set, without scheduling an update - the stamp TrasheableSubscriber writes through an extra update.
EloquentUnitOfWork::setOriginal()
public function setOriginal(object $entity, string $property, mixed $value): voidWhat the unit of work remembers of one property, moved forward (Doctrine's setOriginalEntityProperty()).
EloquentUnitOfWork::scheduledCollectionUpdates()
public function scheduledCollectionUpdates(): arrayThe to-many collections the running flush found changed (Doctrine's getScheduledCollectionUpdates()): each owner, property and collection - one changed since it was read, or one the application made holding elements.
EloquentUnitOfWork::scheduleOrphanRemoval()
public function scheduleOrphanRemoval(object $entity): voidThe entity removed at the next flush as an orphan (Doctrine's scheduleOrphanRemoval()).
EloquentUnitOfWork::cancelOrphanRemoval()
public function cancelOrphanRemoval(object $entity): voidAn orphan removal taken back (Doctrine's cancelOrphanRemoval()).
EloquentUnitOfWork::recomputeWithAssociations()
public function recomputeWithAssociations(object $entity): voidThe entity's change set computed again with its associations (Doctrine's computeChangeSet() on a managed entity): its fields and to-one associations against what they were when last computed - a change found replaces the change set, as Doctrine's does -, then its collections (the join rows of an owning many-to-many, the new entities they reach). What a listener of OnFlush asks after it changed a collection (a reply's followers).
EloquentUnitOfWork::detach()
public function detach(object $entity): voidThe entity forgotten by the unit of work (Doctrine's detach()): not inserted, updated nor deleted by the flush, out of the identity map; nothing cascaded.
EloquentUnitOfWork::clear()
public function clear(): voidEverything forgotten (Doctrine's clear(), what its registry does to the entity manager between two requests: kernel.reset): nothing scheduled, no entity managed, the next reads make new objects; a unit of work a failed flush closed is open again, as the registry makes a new entity manager in place of a closed one. Refused during a flush.
EloquentUnitOfWork::isUninitializedObject()
public function isUninitializedObject(object $entity): boolWhether the entity is a lazy object not read yet (Doctrine's isUninitializedObject()).
EloquentUnitOfWork::cancelDeletion()
public function cancelDeletion(object $entity): voidA removed entity taken back without its other changes being computed (Doctrine's persist() on a removed entity during onFlush): it stays as its row is, unless an extra update writes it.
EntityMap class
final class EntityMap EntityMap.php:30
Where an entity's values are, read from its description: the tables of its class, each field's and each owning association's table and column, its identifier, and how a row says which class it is.
- No inheritance: the entity's table.
- Joined inheritance: the tables from the root's to the class's, each row joined on the identifier; a field or an association sits in the table of the class that maps it (Field::$inheritedFrom), the root's discriminator column says the row's class (Inheritance::$map).
- Single-table inheritance: the root's table for every class, the discriminator naming the row's class; a class below the root reads only the rows of its own value and its subclasses' (discriminatorValues()).
The tables of a query are aliased t0 (the root's), t1... in that order (alias(), column()), the extra tables of a subclass after them; another prefix than "t" names them where the class is joined to another's query (the finder's joins: j1_0, j1_1...).
public readonly array $tablespublic readonly array $identifierpublic readonly string $rootpublic readonly ?Inheritance $inheritancepublic readonly Description $descriptionpublic readonly Entity $entity
EntityMap::__construct()
public function __construct(public readonly Description $description, public readonly Entity $entity)EntityMap::className()
public function className(): stringEntityMap::alias()
public function alias(string $table, string $prefix = 't'): stringThe table alias of one of the class's tables: t0 for the root's (j1_0 under the prefix "j1_").
EntityMap::tableOf()
public function tableOf(string $property): stringThe table holding a field or an owning to-one association's column.
EntityMap::column()
public function column(string $property, string $prefix = 't'): string"alias.column" of a field, or of an owning to-one association's (first) join column.
EntityMap::hasColumn()
public function hasColumn(string $property): boolWhether a field or an owning to-one association has a column of its own (column() answers for it).
EntityMap::joinColumn()
public function joinColumn(Relation $relation): stringThe column an owning to-one association keeps its target's identifier in.
EntityMap::idColumns()
public function idColumns(string $prefix = 't'): array"t0.id": the identifier's column in the root's table (one column; composite identifiers are read by row).
EntityMap::discriminator()
public function discriminator(): ?stringThe discriminator's column in the root's table, null without inheritance.
EntityMap::discriminatorValues()
public function discriminatorValues(): ?arrayThe discriminator values of the class and its subclasses: the rows a single-table query of a class below the root reads. Null when every row of the table is the class's (no inheritance, the root, joined inheritance).
EntityMap::classOf()
public function classOf(array $row): stringThe class a row is, by its discriminator (the class itself without inheritance).
EntityMap::hasSubclasses()
public function hasSubclasses(): boolWhether rows of this class may be of a subclass: an association to it cannot be a ghost of the class itself.
EntityNotFound class
final class EntityNotFound extends RuntimeException EntityNotFound.php:9
A lazy entity (a reference, an association's ghost) whose row is not there when it is first used - deleted since, or left out by a scope -, as Doctrine's EntityNotFoundException says it of a proxy.
EntityNotFound::of()
public static function of(string $class, mixed $id): selfEntityStore class
final class EntityStore EntityStore.php:40
The data mapper: rows of Eloquent's connection read into the application's plain PHP entities, as a description maps them (Omnibridge\Schema), with no Eloquent model - the entities are those Doctrine maps, and nothing in them knows which backend read them.
- The query of a class (query()): its tables joined from the root's (EntityMap), every column selected, the class's discriminator values for a single-table subclass, the store's conditions (a backend's scopes).
- The rows read (rows(), hydrate()): a row of a subclass gets the tables its class adds, read by identifier, then the entity of its class is made without its constructor - or found in the identity map, one object per row - and its properties written raw (no hook, no setter), as Doctrine writes them.
- Values through the Casts, a field mapped on a PHP enumeration (enumType) made one with from(); associations as Doctrine gives them:
- a to-one association: the entity already read, else a PHP 8.4 lazy ghost of the target's class with its identifier set (reading the identifier reads no row), else - a target with subclasses, whose class only its row says, or an inverse one-to-one - the entity read at once;
- a to-many association: a LazyCollection (doctrine/collections' Collection) read on first use, ordered and indexed as declared.
- What each entity held when it was read (original()): its fields and to-one associations, and its to-many collections, which the unit of work compares with what it holds at a flush (Doctrine's original entity data); taken again after a flush wrote it (snapshot()).
- The listeners of a read (onLoad()): told of each entity read once the whole read is done, as Doctrine defers its postLoad to the end of a hydration - the unit of work's PostLoad.
Writing is the unit of work's (EloquentUnitOfWork, Persister): the store gives it the entities' values (value(), setValue()) and keeps its identity map in step (register(), forget()).
EntityStore::__construct()
public function __construct(readonly Connection $connection, readonly Mapping $mapping, readonly Casts $casts, readonly IdentityMap $identityMap = new IdentityMap())EntityStore::connection()
public function connection(): ConnectionEntityStore::mapping()
public function mapping(): MappingEntityStore::casts()
public function casts(): CastsEntityStore::identityMap()
public function identityMap(): IdentityMapEntityStore::queries()
public function queries(): intHow many queries the store ran (the rows of a class, a subclass's tables, a collection), for the tests.
EntityStore::addCondition()
public function addCondition(string $name, \Closure $condition): voidA condition every query of the store adds while it is set (a backend's scope): it receives the class's map, the query, and the prefix its tables are aliased under as EntityMap::alias() says - "t" in the class's own query (its WHERE), another where the finder joins the class to another's query (the join's ON, as Doctrine puts its SQL filters there).
EntityStore::removeCondition()
public function removeCondition(string $name): voidEntityStore::hasCondition()
public function hasCondition(string $name): boolEntityStore::without()
public function without(string $name, \Closure $work): mixed$work run without the condition $name (a backend's scope is "scope:<name>": "scope:trash"), the condition set again after it whatever happens - what Doctrine's SQL filter disabled for one query gives (lesringostars' Subscribers::findOneByEmailIncludingTrashed()).
EntityStore::clear()
public function clear(): voidForgets every entity read: the next read makes new objects.
EntityStore::onLoad()
public function onLoad(\Closure $listener): voidA listener told of each entity read (from a row, into a ghost, by a refresh), once the read that made it is done: all its fields and associations set, the other entities of the same read too.
EntityStore::original()
public function original(object $entity): arrayThe entity's values as read or last flushed, by property: its fields and its to-one associations; [] for an entity the store did not read nor was told was written.
EntityStore::hasOriginal()
public function hasOriginal(object $entity): boolWhether the store holds what the entity was (it read it, or the unit of work wrote it).
EntityStore::originalCollections()
public function originalCollections(object $entity): arrayThe to-many collections of the entity as read or last flushed (the collection objects).
EntityStore::snapshot()
public function snapshot(object $entity): voidWhat the entity holds now becomes what it was: after a flush wrote it.
EntityStore::setOriginal()
public function setOriginal(object $entity, string $property, mixed $value): voidOverwrites the remembered value of one property (Doctrine's setOriginalEntityProperty()).
EntityStore::value()
public function value(object $entity, string $property): mixedThe value a field or an association of the entity holds (null when its property was never set).
EntityStore::setValue()
public function setValue(object $entity, string $property, mixed $value): voidWrites a field or an association of the entity, as Doctrine writes it (no setter).
EntityStore::register()
public function register(object $entity, mixed $id): voidThe entity kept in the identity map under that identifier (a new entity once its row is written).
EntityStore::forget()
public function forget(object $entity): voidThe entity out of the identity map and its remembered values forgotten (its row deleted).
EntityStore::find()
public function find(string $class, mixed $id): ?objectThe entity of that class and identifier, or null: the one read already when there is one (no query), else its row read - of a subclass maybe, as the discriminator says.
EntityStore::findMany()
public function findMany(string $class, array $ids): arrayThe entities of those identifiers, in the order given, those not found left out.
EntityStore::reference()
public function reference(string $class, mixed $id): ?objectThe entity of that class and identifier without reading it: the one read already, else a lazy ghost that reads its row when a field other than its identifier is asked (EntityNotFound then if there is none). A class with subclasses is read at once, its row saying its class (null when there is no row), as Doctrine does.
EntityStore::select()
public function select(string $class, ?\Closure $constrain = null): arrayThe entities of a class whose rows the constraint keeps, in the order it gives (its where, order, limit...), through the identity map.
EntityStore::query()
public function query(EntityMap $map): BuilderThe query of a class: its tables joined (t0 the root's), every column selected under an alias rows() reads, the discriminator values of a single-table subclass, the store's conditions.
EntityStore::constrain()
public function constrain(EntityMap $map, Builder $query, string $prefix): voidThe store's conditions (the scopes enabled) on a class whose tables are aliased under $prefix: its own query's "t", or a join's (JoinClause is a Builder: the conditions go into its ON).
EntityStore::rows()
public function rows(EntityMap $map, Builder $query): arrayThe rows of a query made by query(), each as table => column => value, a subclass's own tables read and added by identifier.
EntityStore::results()
public function results(EntityMap $map, Builder $query): arrayThe entities of a query made by query() with the columns it selects besides theirs (the finder's counts, lengths, groups and selected expressions): each [the entity, the record as the database gave it], in order, one per record - a record repeated by a join gives the same entity again, as Doctrine's simple hydration does.
EntityStore::hydrate()
public function hydrate(EntityMap $map, array $rows): arrayThe entities of rows read by rows(): each of its class, through the identity map.
EntityStore::refresh()
public function refresh(object $entity): boolThe entity read again from its row, its unsaved changes lost; false when its row is gone.
EntityStore::identifier()
public function identifier(object $entity): mixedThe entity's identifier: its value, or property => value for a composite one; read without loading a ghost.
EntityStore::isUninitialized()
public function isUninitialized(object $entity): boolWhether the entity is a lazy ghost no field of which was read yet.
IdentityMap class
final class IdentityMap IdentityMap.php:10
One object per row: the entities a store read (or referenced), by their root class and identifier, so that a row read twice - by id, through an association, in a finder's result - is the same object, as Doctrine's unit of work keeps it.
IdentityMap::__construct()
public function __construct()IdentityMap::key()
public static function key(mixed $id): stringThe key of an identifier: its value, or its values joined for a composite one.
IdentityMap::get()
public function get(string $root, mixed $id): ?objectIdentityMap::add()
public function add(string $root, mixed $id, object $entity): voidIdentityMap::contains()
public function contains(object $entity): boolIdentityMap::remove()
public function remove(object $entity): voidIdentityMap::all()
public function all(): arrayEvery entity kept, by root class in the order the classes were first met, then in the order kept.
IdentityMap::count()
public function count(): intIdentityMap::clear()
public function clear(): voidInvalidPersistence class
final class InvalidPersistence extends InvalidArgumentException InvalidPersistence.php:10
A write the unit of work refuses because the entities asked for it wrongly, where Doctrine's unit of work refuses it too (its ORMInvalidArgumentException): a new entity reached through an association that does not cascade the persist, a cycle of mandatory foreign keys, an entity of no described class.
InvalidPersistence::notCascaded()
public static function notCascaded(string $class, string $property, object $entity): selfInvalidPersistence::cycle()
public static function cycle(array $entities): selfInvalidPersistence::notEntity()
public static function notEntity(object $entity): selfInvalidPersistence::notManaged()
public static function notManaged(object $entity, string $operation): selfInvalidPersistence::invalidAssociation()
public static function invalidAssociation(string $class, string $property, mixed $value): selfLazyCollection class
final class LazyCollection extends AbstractLazyCollection LazyCollection.php:22
A to-many association read when it is first used: doctrine/collections' Collection, which the entities type their associations on (ArrayCollection when they make them, Doctrine's PersistentCollection when Doctrine reads them), loaded by the store on the first call that needs its elements.
It remembers the elements it held when it was read or last flushed (snapshot()), as Doctrine's PersistentCollection does: the unit of work compares them with what it holds now, for the rows of a join table and for orphan removal. A collection never read holds what its snapshot says: nothing changed.
LazyCollection::__construct()
public function __construct(?\Closure $loader, readonly bool $owning = false)$owningthe owning side of a many-to-many: clear() empties its snapshot, as PersistentCollection::clear() does for an owning side
LazyCollection::of()
public static function of(array $elements, bool $owning = false): selfA collection read already, holding those elements as its snapshot: what a flush puts in place of a collection the application made (Doctrine's PersistentCollection in place of an ArrayCollection).
LazyCollection::__serialize()
public function __serialize(): arrayAs Doctrine's PersistentCollection::__sleep() keeps it (step F7d-3): the elements read so far - none but those added when it was never read -, no loader, so that an entity holding it serializes (a signed-in account kept in the session by Symfony's firewall). Unserialized, it is a collection read already, detached from the store.
LazyCollection::__unserialize()
public function __unserialize(array $data): voidLazyCollection::snapshot()
public function snapshot(): arrayThe elements as read or last flushed (read now if the collection was not).
LazyCollection::takeSnapshot()
public function takeSnapshot(): voidWhat it holds now becomes its snapshot (a flush wrote it).
LazyCollection::wasCleared()
public function wasCleared(): boolLazyCollection::isDirty()
public function isDirty(): boolLazyCollection::wrap()
public function wrap(\Closure $wrap): voidThe elements held, once read, by the collection $wrap makes of them (omnibase's OrderedArrayCollection, which sorts them by #[OrderColumn]'s positions on first use): at once for one read already, its entries kept.
LazyCollection::add()
public function add(mixed $element): voidAn element added, the collection not read for it (PersistentCollection::add()): kept until it is read, then after the elements read (unless one of them already).
LazyCollection::remove()
public function remove(string|int $key): mixedLazyCollection::removeElement()
public function removeElement(mixed $element): boolLazyCollection::set()
public function set(string|int $key, mixed $value): voidLazyCollection::clear()
public function clear(): voidLazyCollection::offsetSet()
public function offsetSet(mixed $offset, mixed $value): voidLazyCollection::offsetUnset()
public function offsetUnset(mixed $offset): voidMapping class
final class Mapping Mapping.php:13
The tables of every entity a description holds (EntityMap per class), the class asked by any of its names: an entity's own, or a class alias of it (omnibase's App\Entity\X for Base\Entity\X where the application has none).
public readonly Description $description
Mapping::__construct()
public function __construct(public readonly Description $description)Mapping::of()
public function of(string $class): EntityMapMapping::has()
public function has(string $class): boolMapping::classes()
public function classes(): arrayThe entities the description maps (no mapped superclass, no embeddable).
Persister class
final class Persister Persister.php:22
The statements of a flush, as Doctrine's entity and collection persisters write them, through Eloquent's query builder: each column a change set gives, by the table that holds it (EntityMap).
- insert(): the root's table first with the discriminator (an inheritance), the identifier the database gives read back (AUTO, IDENTITY), then each table the class adds (joined inheritance) with that identifier. A to-one association to an entity whose row is not written yet is written NULL, and returned as an extra update (a nullable foreign key in a cycle, as Doctrine does);
- update(): the changed columns, table by table, by identifier;
- delete(): the join tables' rows of its many-to-many associations (but those the database cascades), then the row of the root's table - the tables a joined class adds go with it by their foreign key, as Doctrine leaves them to the database;
- the rows of a many-to-many association's join table: added, taken out, all of an owner's taken out.
Persister::__construct()
public function __construct(readonly EntityStore $store)Persister::insert()
public function insert(object $entity, array $changeSet, \Closure $pending): arrayInserts the entity's rows; returns the identifier the database gave (null when the application gave it) and the to-one associations written NULL because their target has no row yet.
$changeSetproperty => [before, after]
$pendingwhether an entity's row is still to be written
- Returns
[the generated identifier, the extra update]
Persister::update()
public function update(object $entity, array $changeSet): voidUpdates the changed columns of the entity's rows (an extra update too: its change set is the columns written NULL at its insert).
Persister::delete()
public function delete(object $entity): voidDeletes the entity's row (and the join tables' rows of its many-to-many associations, unless cascaded).
Persister::joinTable()
public function joinTable(EntityMap $map, Relation $relation): arrayThe join table of a many-to-many association, from its owning side's declaration: [table, the owner's column, the target's column, whether the database deletes its rows with an entity (Doctrine's isOnDeleteCascade, of the owning side only), whether the association is to its own class].
Persister::writeJoinRows()
public function writeJoinRows(object $owner, Relation $relation, array $removed, array $added, bool $all = false): voidRows of an owning many-to-many association: those of the targets taken out deleted, those of the targets added inserted (Doctrine's ManyToManyPersister::update()), or every row of the owner deleted first ($all: the collection was replaced).
Persister::generated()
public static function generated(EntityMap $map): boolWhether the class's identifier is the database's (AUTO, IDENTITY), read back after the insert.
UnsupportedPersistence class
final class UnsupportedPersistence extends LogicException UnsupportedPersistence.php:10
What omnibridge/eloquent's unit of work does not do, refused aloud rather than done wrong (omnisense/omnibase's plan "omnibase agnostic", step F7c): an identifier the database cannot give it (a sequence, a custom generator), a composite identifier or join column, a unit of work closed by a failed flush.
UnsupportedPersistence::generator()
public static function generator(string $class, string $strategy): selfUnsupportedPersistence::composite()
public static function composite(string $class, string $what): selfUnsupportedPersistence::closed()
public static function closed(): selfUnsupportedPersistence::operation()
public static function operation(string $operation, string $why): selfOmnibridge\Eloquent\Omnibase
AttributeRelay class
final class AttributeRelay AttributeRelay.php:30
omnibase's behaviour attributes on omnibridge/eloquent's unit of work (plan "omnibase agnostic", step F7c): what omnibridge/doctrine's AttributeSubscriber does on Doctrine's events, on the Lifecycle events the unit of work dispatches at the same moments - a listener of it (EloquentUnitOfWork::listen()).
- The entity's moments (PrePersist ... PostRemove, PostLoad): each property attribute of the entity's class, then each class attribute, that supports the entity, gets its neutral hook (onPrePersist()...). A PreUpdate's setNewValue() is the unit of work's to write (it reads the event's changes back).
- The flush's moments, over buffers kept exactly as AttributeSubscriber keeps them: PreFlush and OnFlush both append the scheduled insertions, updates and deletions to the same buffers without emptying them - so at OnFlush an entity persisted before the flush is in them twice and its OnFlush hooks run twice, as on Doctrine -; a property attribute runs when its property is in the entity's changes or, for a new entity without an identifier and no changes, in its properties (cast_to_array()); a class attribute that ran at PreFlush makes its entity a candidate; PostFlush walks the candidates and the buffers, then empties them all. Doing otherwise changes rows (two slugs, two uuids).
- An attribute that overrides a Doctrine-typed hook of the moment relayed (prePersist(), onFlush()...: an application's or a bundle's, omnibase/marketplace's OrderReference) is refused aloud: there is no Doctrine event to give it.
AttributeRelay::__construct()
public function __construct(AttributeReader|\Closure $attributeReader)$attributeReadera closure is asked at the first event (a host's reader, made after the persistence it is made with: step F7d)
AttributeRelay::attach()
public static function attach(EloquentUnitOfWork $unitOfWork, AttributeReader|\Closure|null $attributeReader = null): selfThe relay listening to the unit of work's events.
AttributeRelay::attributeReader()
public function attributeReader(): AttributeReaderThe reader the behaviours are read with: the one given, or the host's, asked once.
AttributeRelay::__invoke()
public function __invoke(object $event): voidEloquentBackend class
final class EloquentBackend implements Backend EloquentBackend.php:22
omnisense/omnibridge's Backend on omnibridge/eloquent (plan "omnibase agnostic", step F7b): the name
"eloquent", what it can do (lazy associations: ghosts and lazy collections; no second-level or result cache;
transactions, with the writes since F7c), its unit of work, and omnibase's scopes - the trash and the vault -
added to every query of the store while they are enabled, as Doctrine's TrashFilter and VaultFilter are: a
scope's criteria (Scope::criteria()) on the entity's columns, deletedAt IS NULL, vault IS NULL OR vault = :environment
- in the class's own query, and in the ON of a join of it (the finder's), as Doctrine puts its filters there.
EloquentBackend::__construct()
public function __construct(readonly EloquentUnitOfWork $unitOfWork, array $scopes = [])$scopesmore scopes than omnibase's trash and vault
EloquentBackend::name()
public function name(): stringEloquentBackend::supports()
public function supports(string $feature): boolEloquentBackend::unitOfWork()
public function unitOfWork(): UnitOfWorkEloquentBackend::enableScope()
public function enableScope(string $name, array $parameters = []): voidEloquentBackend::disableScope()
public function disableScope(string $name): voidEloquentBackend::isScopeEnabled()
public function isScopeEnabled(string $name): boolEloquentBehaviours class
final class EloquentBehaviours EloquentBehaviours.php:38
The behaviours' parts on omnibridge/eloquent (plan "omnibase agnostic", step F7c), registered for EloquentUnitOfWork with omnisense/omnibase's Backends where omnibridge/doctrine's DoctrineBehaviours registers Doctrine's: #[Vault]'s forced update, #[Slugify]'s pending writes and unique index, #[Cache]'s eviction (no second-level cache), the #[OrderColumn]'s lazy order; the entities' shapes (the store's description); what the core's services ask beyond the unit of work (row locks, conditional updates, the entity cache, deletes by criteria); the column types holding arrays; the backend and its scopes; the repositories (the persistence's own, EloquentPersistence's).
const BACKENDS = [VaultBackend::class => EloquentVaultBackend::class, SlugifyBackend::class => EloquentSlugifyBackend::class, CacheBackend::class => EloquentCacheBackend::cla…
EloquentBehaviours::register()
public static function register(): voidEloquentBehaviours::ensureRegistered()
public static function ensureRegistered(): voidEloquentBehaviours::remember()
public static function remember(EloquentPersistence $persistence): voidThe persistence a unit of work belongs to: its backend and repositories are the ones its behaviours ask for.
EloquentBehaviours::persistence()
public static function persistence(EloquentUnitOfWork $unitOfWork): ?EloquentPersistenceEloquentEntities class
class EloquentEntities implements Entities EloquentEntities.php:32
omnibase's repository on the store (plan "omnibase agnostic", step F7b): the core's Entities - find(), findAll(), findBy(), findOneBy(), count() - and the finder language (findBySlug(), cacheOneByStateAndSlugStartingWith(), countForParentByState()...), both compiled by EloquentFinder on Illuminate's query builder as omnibridge/doctrine's ServiceEntityRepository compiles them on Doctrine: findBy()'s criteria array reads the words a name would (a list IN, a Key without a join, a Group in parentheses, an association joined), its order the finder's (a path, FIELD(), RAND()). A finder that hands back Doctrine's Query hands back a FinderQuery (getResult(), getOneOrNullResult()).
The base of the core's repositories on Eloquent (Repository\*) and the repository of any other class. persist(), remove() and flush() write through the unit of work (step F7c), as ServiceEntityRepository writes through the entity manager: an entity of another class refused; a repository made without a unit of work refuses to write (UnsupportedPersistence).
EloquentEntities::__construct()
public function __construct(protected readonly EntityStore $store, protected readonly string $class, protected readonly ?EloquentUnitOfWork $unitOfWork = null)EloquentEntities::unitOfWork()
public function unitOfWork(): EloquentUnitOfWorkThe unit of work the repository writes through (refused when it was made without one).
EloquentEntities::getClassName()
public function getClassName(): stringThe class the repository reads (its rows: of it and its subclasses).
EloquentEntities::entityMap()
public function entityMap(): EntityMapThe class's tables and columns (EntityMap).
EloquentEntities::finder()
public function finder(): EloquentFinderEloquentEntities::__call()
public function __call(string $method, array $arguments): mixedThe finder language: findBy...(), findOneBy...(), cache...(), count...(), lengthOf...(), sumOf...().
..
EloquentEntities::find()
public function find($id): ?objectEloquentEntities::findAll()
public function findAll(): arrayEloquentEntities::findBy()
public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): arrayEloquentEntities::findOneBy()
public function findOneBy(array $criteria, ?array $orderBy = null): ?objectEloquentEntities::count()
public function count(array $criteria = []): intEloquentEntities::findByExample()
public function findByExample(object $select, ?array $orderBy = null, $limit = null, $offset = null): arrayQuery-by-Example (ServiceEntityRepository::findByExample()): the set fields and to-one associations of a select object as findBy()'s criteria; a select setting none refused, rather than every row read.
EloquentEntities::criteriaFromSelect()
public function criteriaFromSelect(object $select): arrayEloquentEntities::persist()
public function persist($entity, bool $flush = false): voidEloquentEntities::remove()
public function remove($entity, bool $flush = false): voidEloquentEntities::flush()
public function flush(bool $autoclear = false)EloquentPersistence class
final class EloquentPersistence EloquentPersistence.php:38
omnibase's entities on an Eloquent connection, in one call (plan "omnibase agnostic", step F7b): the description of the core's and the application's entities (EntitySchema, no other persistence asked), the store reading them with omnibase's column types (OmnibaseCasts), the unit of work, the backend and its scopes, the repositories.
$persistence = EloquentPersistence::create(Connections::url($_ENV['DATABASE_URL']), ['project_dir' => $projectDir]); $article = $persistence->repositories()->oneById(Article::class, 12);
Options: EntitySchema's (project_dir, enumerations, types, resolve_target_entities, rules, column_types),
directories (more entity folders, a bundle's), repositories (an application's repositories on the store, by
entity: EloquentRepositories::register()) and dispatcher (the host's PSR-14 dispatcher, given the unit of work's
Lifecycle events), lifecycle (omnibase's behaviours and listeners on the unit of work: OmnibaseListeners'
options, step F7c) and listeners (the host's packages' listeners of those events, omnisense/omnibridge's
Lifecycle\Listeners: an iterable or a closure of callables, made at the first event, called after omnibase's - step B2). The associations cascade as their mapping and omnibase's #[Cascade] and #[OrphanRemoval] say
(OmnibaseCascades). The behaviours' parts are registered for the unit of work (EloquentBehaviours).
const HOST_SERVICES = ['attribute_reader' => 'Base\Attributes\AttributeReader', 'mention_enhancer' => 'Base\Service\Model\Wysiwyg\MentionEnhancerInterface', 'setting_bag' => 'Base…The services of a host omnibase's lifecycle is attached with, by OmnibaseListeners' option (step F7d): each asked of the host's container when it is first needed, since most are made with this persistence's unit of work.
EloquentPersistence::create()
public static function create(Connection $connection, array $options = [], ?Description $description = null, ?Casts $casts = null): selfEloquentPersistence::host()
public static function host(Connection $connection, ContainerInterface $services, array $options = [], ?Description $description = null): selfomnibase's persistence as a host makes it, the one its container gives (plan "omnibase agnostic", step F7d:
omnibridge/symfony with base.persistence: eloquent, omnibridge/laravel, Omnibridge\Container): on the host's
connection, with the options (EntitySchema's, directories, repositories, dispatcher) and omnibase's
lifecycle attached from the host's services (HOST_SERVICES, each found by has() now and made by get() when it is
first needed: they are made with this persistence) - lifecycle gives more of OmnibaseListeners' options over
them: empty_trash, max_revisions (the host's base.extension.* parameters), entity_dispatchers (the host's
own, an iterable or a closure of them: their life is the container's). Without an AttributeReader (Doctrine's
metadata builds it: none in plain PHP), the behaviours cannot run: the entities are read as they are stored and
a flush that writes is refused aloud.
EloquentPersistence::fromContainer()
public static function fromContainer(ContainerInterface $container): selfomnibase's persistence in plain PHP (Omnibridge\Container, the definitions of Omnibridge\Eloquent\Container):
its connection the container's Illuminate\Database\Connection, else Capsule on the parameter database.url,
else on DATABASE_URL; its description the container's Omnibridge\Schema\Description, else the entities of
kernel.project_dir (the current folder by default); the parameters base.extension.empty_trash and
max_revisions; the services tagged base.entity_dispatcher, when it has tags (Omnibridge\Container::tagged());
the trash scope on, and the vault's for kernel.environment (prod by default), as the hosts enable them.
EloquentPersistence::reset()
public function reset(): voidBetween two requests or messages (Symfony's kernel.reset, Laravel's scoped reset, a worker's loop): the unit of work cleared - nothing scheduled, no entity managed, a closed one open again -, as Doctrine's registry resets its entity manager.
EloquentPersistence::lifecycle()
public function lifecycle(): ?OmnibaseListenersThe behaviours' relay and the listeners' adapters attached by the option "lifecycle" (null without it).
EloquentPersistence::store()
public function store(): EntityStoreEloquentPersistence::unitOfWork()
public function unitOfWork(): EloquentUnitOfWorkEloquentPersistence::backend()
public function backend(): EloquentBackendEloquentPersistence::repositories()
public function repositories(): EloquentRepositoriesEloquentRepositories class
final class EloquentRepositories implements Repositories EloquentRepositories.php:18
omnibase's Repositories on the store (plan "omnibase agnostic", step F7b): the repository of an entity - the core's on Eloquent (Repository\*, each implementing the core's interface: Threads, Users, Comments...) for its entity and the entity's subclasses (App\Entity\Article\Article gets ThreadRepository's), an application's own where one is registered (register()), EloquentEntities for any other class (find, findBy, count and the finder language) -, and the entities of identifiers: one query for those not read yet, the identity map for the others.
const CORE = [ \Base\Entity\User::class => R\UserRepository::class, \Base\Entity\Thread::class => R\ThreadRepository::class, \Base\Entity\ThreadIntl::class =>…The core's entities and their repository on Eloquent, as omnibridge/doctrine's repositories serve the core's interfaces (Base\Repository\Aliases::INTERFACES).
EloquentRepositories::__construct()
public function __construct(readonly EntityStore $store, array $classes = [], readonly ?EloquentUnitOfWork $unitOfWork = null)EloquentRepositories::register()
public function register(string $entity, string $repository, ?\Closure $factory = null): voidAn application's repository for an entity and its subclasses (its own class extending EloquentEntities, or one of the core's repositories), in place of the core's or the plain one. $factory makes it when it needs more than the store, the class and the unit of work (a cache: lesringostars' comments' counts), given those three.
EloquentRepositories::of()
public function of(string $class): EntitiesEloquentRepositories::implementing()
public function implementing(string $interface, ?string $class = null): EntitiesThe repository implementing one of the core's interfaces (Threads, Users, Comments...): the entity's whose repository class implements it. A class of the application named when its entity is the application's (Users: App\Entity\User).
$classthe entity to read, the interface's own by default
EloquentRepositories::repositoryClass()
public function repositoryClass(string $class): stringEloquentRepositories::byIds()
public function byIds(string $class, array $ids): arrayEloquentRepositories::oneById()
public function oneById(string $class, mixed $id): ?objectOmnibaseCascades class
final class OmnibaseCascades OmnibaseCascades.php:18
omnibase's own cascade declarations on Eloquent (plan "omnibase agnostic", step F7c): #[Cascade(value: [...])] and
#[OrphanRemoval] on an association's property, or on its class with the property named (column), which on Doctrine
rewrite the association's mapping when its metadata is loaded (their loadClassMetadata()). Read here from the
attributes' arguments, nothing instantiated: what Cascades::extend() takes. And the translations' association, which
omnibridge/doctrine's IntlSubscriber maps (step F7c).
OmnibaseCascades::resolver()
public static function resolver(): \ClosureOmnibaseCasts class
final class OmnibaseCasts OmnibaseCasts.php:20
omnibase's column types read as omnibridge/doctrine's DBAL types read them (plan "omnibase agnostic", step F7b):
- datetime and datetimetz in UTC, utc_datetime and utc_datetime_immutable (Casts::utc());
array: PHP's serialization (omnibridge/doctrine's ArrayType);- the passkeys' columns: passkey_base64 (base64 of the bytes), passkey_aaguid (a string), passkey_trust_path (JSON);
- each enumeration and set of the core, the application and the folders given (EntitySchema::types()), through the enumeration's own toPHPValue()/toDatabaseValue(), as EnumTypeAdapter calls them;
- the application's own types: EntitySchema::columnTypes()'s aliases and the column_types option.
OmnibaseCasts::create()
public static function create(array $options = []): Casts$optionsEntitySchema's options (project_dir, enumerations, types, column_types)
Omnibridge\Eloquent\Omnibase\Behaviour
EloquentBulkDeletes class
final class EloquentBulkDeletes implements BulkDeletes EloquentBulkDeletes.php:17
BulkDeletes on omnibridge/eloquent (plan "omnibase agnostic", step F7c): the rows of a class whose fields equal the criteria deleted in statements, no entity read nor event dispatched - DoctrineBulkDeletes' DQL DELETE: the class's rows only (a single-table class by its discriminator), the store's scopes applied (Doctrine's filters), and for a joined hierarchy every table of it, the subclasses' first (Doctrine's multi-table delete). The number of rows.
EloquentBulkDeletes::__construct()
public function __construct(readonly EloquentUnitOfWork $unitOfWork)EloquentBulkDeletes::deleteWhere()
public function deleteWhere(string $class, array $criteria): intEloquentBulkDeletes::deleteIds()
public function deleteIds(string $class, array $ids): intThe rows of those identifiers deleted, in each table of the class (the subclasses' first): what a DQL
DELETE FROM <class> e WHERE e.id IN (:ids) deletes (VersionableSubscriber's trimming). The number of rows.
EloquentCacheBackend class
final class EloquentCacheBackend implements CacheBackend EloquentCacheBackend.php:17
#[Cache]'s part on omnibridge/eloquent (plan "omnibase agnostic", step F7c): the store keeps no second-level cache, so nothing is evicted. What DoctrineCacheBackend does whether a cache is configured or not stays: for the entity itself, each association whose target is cached is read through its getter first (a lazy one is loaded), so that the entity is in the same state on both backends when its row is written.
EloquentCacheBackend::__construct()
public function __construct(readonly EloquentUnitOfWork $unitOfWork)EloquentCacheBackend::evict()
public function evict(Cache $cache, object $entity, ?string $property = null): voidEloquentColumnTypes class
final class EloquentColumnTypes implements ColumnTypes EloquentColumnTypes.php:13
ColumnTypes on omnibridge/eloquent (plan "omnibase agnostic", step F7c): a field holds a PHP array when its type is
json or a set enumeration (the store's casts know the core's and the application's, OmnibaseCasts) - what
DoctrineColumnTypes answers from Doctrine's types.
EloquentColumnTypes::__construct()
public function __construct(readonly EloquentUnitOfWork $unitOfWork)EloquentColumnTypes::isArray()
public function isArray(string $type): boolEloquentConditionalUpdates class
final class EloquentConditionalUpdates implements ConditionalUpdates EloquentConditionalUpdates.php:12
ConditionalUpdates on omnibridge/eloquent (plan "omnibase agnostic", step F7c): the field's column set to a new value where it still holds the old one, in one statement (DoctrineConditionalUpdates' DQL UPDATE); true when the row was.
EloquentConditionalUpdates::__construct()
public function __construct(readonly EloquentUnitOfWork $unitOfWork)EloquentConditionalUpdates::compareAndSet()
public function compareAndSet(object $entity, string $field, mixed $from, mixed $to): boolEloquentEntityCache class
final class EloquentEntityCache implements EntityCache EloquentEntityCache.php:9
EntityCache on omnibridge/eloquent (plan "omnibase agnostic", step F7c): the store keeps no second-level cache.
EloquentEntityCache::__construct()
public function __construct(readonly EloquentUnitOfWork $unitOfWork)EloquentEntityCache::enabled()
public function enabled(): boolEloquentEntityCache::evict()
public function evict(string $class, mixed $id): voidEloquentEntityCache::evictClass()
public function evictClass(string $class): voidEloquentOrderColumnBackend class
final class EloquentOrderColumnBackend implements OrderColumnBackend EloquentOrderColumnBackend.php:16
#[OrderColumn]'s part on omnibridge/eloquent (plan "omnibase agnostic", step F7c): a to-many association the store reads lazily is ordered by the stored positions without being read now - its elements are held, once it is read, in omnibase's OrderedArrayCollection, which sorts itself on its first use (what DoctrineOrderColumnBackend does inside Doctrine's PersistentCollection); one read already is wrapped the same way, its entries kept.
EloquentOrderColumnBackend::__construct()
public function __construct(readonly EloquentUnitOfWork $unitOfWork)EloquentOrderColumnBackend::orderLazily()
public function orderLazily(object $entity, mixed $collection, array $positions): boolEloquentRowLocks class
final class EloquentRowLocks implements RowLocks EloquentRowLocks.php:13
RowLocks on omnibridge/eloquent (plan "omnibase agnostic", step F7c): the work run in a transaction holding the entity's row (SELECT ... FOR UPDATE, as Doctrine's PESSIMISTIC_WRITE lock reads it; SQLite has no row lock, its transaction is the lock).
EloquentRowLocks::__construct()
public function __construct(readonly EloquentUnitOfWork $unitOfWork)EloquentRowLocks::locked()
public function locked(object $entity, callable $work): mixedEloquentSlugifyBackend class
final class EloquentSlugifyBackend implements SlugifyBackend EloquentSlugifyBackend.php:14
#[Slugify]'s part on omnibridge/eloquent (plan "omnibase agnostic", step F7c): the writes of the running flush - its insertions, then its updates, in the order the unit of work scheduled them, as DoctrineSlugifyBackend lists Doctrine's -, and whether the database still holds a unique index on the slug's column alone (read from the database's indexes through Illuminate's schema builder, once per process and column).
EloquentSlugifyBackend::__construct()
public function __construct(readonly EloquentUnitOfWork $unitOfWork)EloquentSlugifyBackend::pendingWrites()
public function pendingWrites(): arrayEloquentSlugifyBackend::uniqueAlone()
public function uniqueAlone(string $class, string $property): boolEloquentVaultBackend class
final class EloquentVaultBackend implements VaultBackend EloquentVaultBackend.php:12
#[Vault]'s part on omnibridge/eloquent (plan "omnibase agnostic", step F7c): a secured field given a new plain value is written again, the entity scheduled for an update whatever its change set says - Doctrine's scheduleForUpdate().
EloquentVaultBackend::__construct()
public function __construct(readonly EloquentUnitOfWork $unitOfWork)EloquentVaultBackend::scheduleUpdate()
public function scheduleUpdate(object $entity): voidOmnibridge\Eloquent\Omnibase\Finder
EloquentFinder class
class EloquentFinder EloquentFinder.php:48
omnibase's finder language on Illuminate's query builder (plan "omnibase agnostic", step F7b): the core's Finder\Parser reads a finder's name and arguments (read()), this class compiles the Query into the store's query of the class and runs it (execute()) - what omnibridge/doctrine's ServiceEntityParser does on Doctrine, word for word, so that one name gives the same rows on both persistences (FinderParityTest):
- every word of a criterion: EqualTo (= or IN for a list, an empty list no condition), NotEqualTo, GreaterThan, GreaterEqualTo, LowerThan, LowerEqualTo; the dates YoungerThan, YoungerEqualTo, OlderThan, OlderEqualTo, Within (an age or an offset from now, to the minute), IsOver, IsNotOver; StartingWith, EndingWith and their Not (LIKE, the value literal: "%", "_" and "!" escaped with "!", ESCAPE '!'), Partial (LIKE as given), Insensitive (LOWER()), Null, Empty, True, False and their Not; ClosestTo and FarestTo (ABS(x - value) ordering the rows); InstanceOf, ClassOf and their Not (the discriminator); But; WithRoute; Model (a Query-by-Example); a JSON field compared as Doctrine's JSON_CONTAINS();
- a criterion on a to-one or to-many association, or a path through one ("translatable.state"), through a LEFT
JOIN of it - the store's conditions (the trash and vault scopes) in the join's ON, as Doctrine's SQL filters, a
subclass target's discriminator there too; a translation's (Translatable's
translations) on the translation's own foreign key in the root table of its hierarchy, as omnibridge/doctrine's TranslatableWalker rewrites it; - a key criterion (Finder\Key): the association's own foreign key, no join; a group (Finder\Group): its members in parentheses;
- the requests: find (One, All, Randomly, AtMost<N>, Last<N>, LastOne, Previous<N>, PreviousOne, Next<N>, NextOne), count and distinctCount (For<column>, grouped: the rows with their count), lengthOf<column> (LENGTH(), or a collection's size), sumOf, minOf, maxOf;
- order (a field, an association's field, a list of values - FIELD() -, id => "rand" - RAND() -, a selected value's name, an expression of Expressions), limit, offset, grouping, selectAs.
What it cannot express is refused aloud with UnsupportedQueryException - MemberOf (omnibridge/doctrine compiles it
to e MEMBER OF <class>, which DQL refuses too), a Partial association, a list compared Partial, a path deeper than
one association, a criterion on a JSON field through a path, an expression it does not translate; what Doctrine
refuses (an unknown separator, an operator a list or a JSON field does not take, an Older/Younger date) is refused
with the same message. Cache (the cache... names) and Eagerly change no row: the store has no result cache, and
reads associations lazily.
EloquentFinder::__construct()
public function __construct(readonly EntityStore $store, readonly EntityMap $map, readonly ?\Closure $routeParameters = null)$routeParametersa host's request => its route parameters (WithRoute), false for anything else
EloquentFinder::subject()
public function subject(): EntitySubjectEloquentFinder::read()
public function read(string $method, array $arguments): QueryReads a finder's name and arguments into the finder language's neutral form (Finder\Parser), nothing run.
EloquentFinder::parse()
public function parse(string $method, array $arguments): mixedReads a finder's name and arguments, then compiles and runs it.
EloquentFinder::execute()
public function execute(Query $query): mixedCompiles a finder call read by Finder\Parser and runs it: the internal request it names (__findBy, __findOneBy, __countBy...) with its arguments, the criteria's words, the separator and the column set for the time of the call.
EloquentFinder::routeParameters()
public static function routeParameters(mixed $argument): array|null|falseA host's request for WithRoute: Symfony's Request or kernel event (their attributes' _route_params), Laravel's Request (its route's parameters); false for anything else, which the Parser refuses.
EntitySubject class
final class EntitySubject implements Subject EntitySubject.php:17
What omnibase's finder language asks of an entity (Base\Database\Repository\Finder\Subject), answered from its description (plan "omnibase agnostic", step F7b): its class, its fields and associations, the names a criterion may give them - its aliases (#[Alias]), a field by its column, as omnibridge/doctrine's ClassMetadataManipulator:: getFieldNames() reads them from Doctrine's metadata -, and a Query-by-Example's criteria (the set fields and to-one associations of the object given, as ServiceEntityRepository::criteriaFromSelect() reads them).
EntitySubject::__construct()
public function __construct(readonly EntityMap $map)EntitySubject::map()
public function map(): EntityMapEntitySubject::getClassName()
public function getClassName(): stringEntitySubject::getFieldNames()
public function getFieldNames(): arrayEntitySubject::hasField()
public function hasField(string $name): boolEntitySubject::isField()
public function isField(string $name): boolEntitySubject::isAssociation()
public function isAssociation(string $name): boolEntitySubject::relation()
public function relation(string $name): ?RelationEntitySubject::typeOf()
public function typeOf(string $path, \Closure $mapOf): ?stringThe type of a field, through a to-one association for a path ("translatable.state"); null for anything else.
EntitySubject::alias()
public function alias(?string $name): ?stringThe property a name gives (an alias, a column, a field, an association), the name itself when it is none - ServiceEntityParser::getAlias().
EntitySubject::criteriaFromSelect()
public function criteriaFromSelect(object $select): arrayFinderQuery class
final class FinderQuery implements IteratorAggregate, Pages FinderQuery.php:27
What a finder hands back where omnibridge/doctrine hands back Doctrine's Query (findBy...(), findAll(), findLast...(), findAtMost...(), findPrevious...(), findNext...(), findRandomly...()): the compiled query, run when its result is asked - getResult(), getOneOrNullResult() -, as often as it is asked.
The result has Doctrine's shapes: the entities, in the order of their first row (a row repeated by a join of a to-many association gives no second result, as Doctrine's ObjectHydrator keeps one per root entity; the LIMIT counts rows, as Doctrine's SQL does); with other values selected (a grouping, selectAs, a count, a length), a row per entity - ["entity" => the entity, ...] when grouped, [0 => the entity, ...] otherwise -, the values as the database gives them, in the order they were selected, a repeated entity's row taking the last row's.
It is also omnibase's Pages (Base\Service\Model\Pages: what Paginator::paginate() and Pagination page through, where omnibridge/doctrine adapts Doctrine's Query with QueryPages): the entities counted once each, a page of them by the query's own order (plan "omnibase agnostic", step F7d-2: a records picker's pages, RemoteSearch).
FinderQuery::__construct()
public function __construct(readonly EntityStore $store, readonly EntityMap $map, readonly Builder $query, readonly int|string|null $entityKey, readonly array $columns)$columnsa mixed result's key => the column it is read from
FinderQuery::getResult()
public function getResult(): arrayFinderQuery::getOneOrNullResult()
public function getOneOrNullResult(): mixedThe first result, null without one; more than one refused, as Doctrine's NonUniqueResultException does.
FinderQuery::getSQL()
public function getSQL(): stringThe SQL Illuminate runs (its placeholders), for a test or a log.
FinderQuery::getParameters()
public function getParameters(): array- Returns
the values bound, in order
FinderQuery::getFirstResult()
public function getFirstResult(): intFinderQuery::getMaxResults()
public function getMaxResults(): ?intFinderQuery::builder()
public function builder(): BuilderFinderQuery::count()
public function count(): intThe entities the query finds, each counted once, as QueryPages counts a DQL query's (the root entity's identifier, distinct): its conditions, joins and groups kept, its order, limit and offset left out.
FinderQuery::slice()
public function slice(int $offset, int $limit): arrayOne page of the results, by the query's order, $limit entities from the $offset-th, as QueryPages pages a DQL query by its root entities: without a join, the rows themselves; with one (a to-many join repeats an entity), the entities' identifiers in the query's order first, the page's then read.
FinderQuery::getIterator()
public function getIterator(): \ArrayIteratorOmnibridge\Eloquent\Omnibase\Lifecycle
DemoAccountLockListener class
final class DemoAccountLockListener DemoAccountLockListener.php:18
A demonstration account kept as declared, on omnibridge/eloquent (plan "omnibase agnostic", step F7c): omnibridge/doctrine's DemoAccountLockSubscriber, the rule the core's (DemoAccountLock). During a request, at PreFlush: a declared account's deletion refused, and each declared account the unit of work holds given back its identifier, address, password and second factor (the values read and written as the store holds them), the visitor told once.
DemoAccountLockListener::__construct()
public function __construct(DemoAccountLock|\Closure $lock, readonly ?Requests $requests = null)$locka closure is asked at the first flush during a request (a host's service: step F7d), none means nothing to keep
DemoAccountLockListener::__invoke()
public function __invoke(object $event): voidDemoAccountLockListener::reset()
public function reset(): voidEloquentObjectManager class
final class EloquentObjectManager implements ObjectManager EloquentObjectManager.php:19
doctrine/persistence's ObjectManager over omnibridge/eloquent's unit of work (plan "omnibase agnostic", step F7c): what the lifecycle arguments of omnibase's entity dispatchers carry (their subclasses type their hooks on Doctrine\Persistence\Event\LifecycleEventArgs: lesringostars' NewsletterEventDispatcher). The unit of work's operations; Doctrine's metadata and repositories are refused aloud (there are none: the description and omnisense/omnibase's Repositories stand in their place).
EloquentObjectManager::__construct()
public function __construct(readonly EloquentUnitOfWork $unitOfWork)EloquentObjectManager::unitOfWork()
public function unitOfWork(): EloquentUnitOfWorkEloquentObjectManager::find()
public function find(string $className, mixed $id): ?objectEloquentObjectManager::persist()
public function persist(object $object): voidEloquentObjectManager::remove()
public function remove(object $object): voidEloquentObjectManager::clear()
public function clear(): voidEloquentObjectManager::detach()
public function detach(object $object): voidEloquentObjectManager::refresh()
public function refresh(object $object): voidEloquentObjectManager::flush()
public function flush(): voidEloquentObjectManager::getRepository()
public function getRepository(string $className): ObjectRepositoryEloquentObjectManager::getClassMetadata()
public function getClassMetadata(string $className): ClassMetadataEloquentObjectManager::getMetadataFactory()
public function getMetadataFactory(): ClassMetadataFactoryEloquentObjectManager::initializeObject()
public function initializeObject(object $obj): voidEloquentObjectManager::isUninitializedObject()
public function isUninitializedObject(mixed $value): boolEloquentObjectManager::contains()
public function contains(object $object): boolEntityDispatcherListener class
final class EntityDispatcherListener EntityDispatcherListener.php:25
omnibase's entity dispatchers on omnibridge/eloquent (plan "omnibase agnostic", step F7c): an AbstractEventDispatcher (the user.* and thread.* events, an application's own: lesringostars' newsletter.*) called at the moments Doctrine calls it - before a write it notes its events, after it dispatches them.
On the core's neutral hooks (persisting(), updating(), removing(); step B, leftover (a)) the dispatcher is given the unit of work's own Lifecycle events (AbstractEventDispatcher::lifecycle()): nothing of doctrine/persistence. One that still overrides a former hook typed on doctrine/persistence's LifecycleEventArgs (AbstractEventDispatcher::formerHooks(), or every dispatcher under a core without lifecycle()) is called the former way, with those arguments over the unit of work (EloquentObjectManager; a PreUpdate's carry its changes, PreUpdateArgs) - refused aloud without doctrine/persistence. The dispatcher is made on the Eloquent unit of work (its hydrator's snapshots are the store's); its pending flush is the host's, as under Doctrine (AbstractEventDispatcher::live()). A dispatcher overriding the Doctrine-typed postFlush() is refused: nothing calls it here, and its pending events are flushed by the host.
EntityDispatcherListener::__construct()
public function __construct(readonly AbstractEventDispatcher $dispatcher, EloquentUnitOfWork $unitOfWork)EntityDispatcherListener::dispatcher()
public function dispatcher(): AbstractEventDispatcherEntityDispatcherListener::former()
public function former(): boolWhether the dispatcher is called with doctrine/persistence's LifecycleEventArgs (a former hook overridden).
EntityDispatcherListener::__invoke()
public function __invoke(object $event): voidEntityDispatchersListener class
final class EntityDispatchersListener EntityDispatchersListener.php:17
A host's entity dispatchers on omnibridge/eloquent (plan "omnibase agnostic", step F7d): the services its container makes (Symfony's tagged base.entity_dispatcher, Laravel's, Omnibridge\Container's), on the unit of work the container gives - this persistence's -, read at the first entity event, since they are made with it. Each is then called as EntityDispatcherListener calls one, in their order. They are the container's, not made here: their life is the container's, the one this persistence lives in, so the host's flush of what they left pending (flushPending(), AbstractEventDispatcher::live()) never reaches a unit of work another persistence holds.
EntityDispatchersListener::__construct()
public function __construct(readonly iterable|\Closure $dispatchers, readonly EloquentUnitOfWork $unitOfWork)EntityDispatchersListener::__invoke()
public function __invoke(object $event): voidEntityDispatchersListener::listeners()
public function listeners(): array- Returns
one per dispatcher, in their order
EntityDispatchersListener::dispatchers()
public function dispatchers(): arrayIntlListener class
final class IntlListener IntlListener.php:22
omnibase's translations on omnibridge/eloquent (plan "omnibase agnostic", step F7c): what omnibridge/doctrine's IntlSubscriber does at the flush and the reads (its mapping part - the translations' association, cascades, unique locale - is the description's and OmnibaseCascades' here; its query part, TranslatableWalker, the finder's join).
- PostLoad: an empty translation read is removed as an orphan at the next flush.
- PrePersist and PreFlush: the pending translations of a translatable (new, or every one the unit of work holds) committed into its collection.
- OnFlush: each translation and translatable the flush writes (and each owner of a collection it finds changed) made consistent - an empty new translation dropped (detached), a locale given from its key, the translatable set; an empty translation the database holds deleted, a non-empty one's orphan removal taken back.
IntlListener::__invoke()
public function __invoke(object $event): voidOmnibaseListeners class
final class OmnibaseListeners OmnibaseListeners.php:44
omnibase's lifecycle on omnibridge/eloquent's unit of work, in one call (plan "omnibase agnostic", step F7c): the behaviours' relay and the adapters of the listeners omnibridge/doctrine and omnibase register on Doctrine's events, listening in Doctrine's order (by priority, then as they are declared: AttributeSubscriber and IntlSubscriber 2048, TrasheableSubscriber 1024, VersionableSubscriber 512, then ThreadSubscriber, SettingSubscriber, TextOverrideCacheListener, the entity dispatchers, UserSubscriber's and DemoAccountLockSubscriber's preFlush).
Each adapter is attached when what it needs is given (a host wires them from its container, step F7d):
OmnibaseListeners::attach($persistence->unitOfWork(), [
'empty_trash' => '+7 days', 'max_revisions' => 5, // TrasheableListener, VersionableListener
'mention_enhancer' => fn () => $mentionEnhancer, // ThreadListener
'setting_bag' => fn () => $settingBag, // SettingListener
'translator' => fn () => $overridingTranslator, // TextOverrideListener
'dispatcher' => $psr14, 'requests' => $requests, // the entity dispatchers' events
'entity_dispatchers' => [UserEventDispatcher::class, ...], // made on this unit of work (or the
// host's, an iterable or a closure: read lazily)
'user_subscriber' => fn () => $userSubscriber, // its preFlush()
'demo_lock' => $demoAccountLock, // DemoAccountLockListener
'entity_extension' => $entityExtension, // refused aloud when it holds an extension
]);Not adapted, with the reason: InverseCollectionCacheSubscriber (it evicts Doctrine's second-level cache: the store keeps none); TrackingPolicySubscriber and the listeners' loadClassMetadata/resolveDiscriminator (Doctrine's mapping: the description is the store's); IntlSubscriber's onQuery (TranslatableWalker: the finder joins the translations itself); ExtensionSubscriber's entries of an EntityExtension (no extension is registered by omnibase, its bundles or lesringostars: refused aloud when one is).
OmnibaseListeners::attach()
public static function attach(EloquentUnitOfWork $unitOfWork, array $options = []): selfOmnibaseListeners::listeners()
public function listeners(): array- Returns
the relay and the adapters, in the order they listen
OmnibaseListeners::get()
public function get(string $class): ?objectThe adapter of that class, or null.
PreFlushListener class
final class PreFlushListener PreFlushListener.php:11
A service's preFlush() called as each flush begins, on omnibridge/eloquent (plan "omnibase agnostic", step F7c): omnisense/omnibase's UserSubscriber, whose preFlush() takes no Doctrine argument (the tokens it revokes).
PreFlushListener::__construct()
public function __construct(readonly \Closure $service)$servicea service with a preFlush() taking no argument
PreFlushListener::__invoke()
public function __invoke(object $event): voidPreUpdateArgs class
final class PreUpdateArgs extends LifecycleEventArgs PreUpdateArgs.php:14
doctrine/persistence's lifecycle arguments of a PreUpdate, with its changes (getEntityChangeSet(), as Doctrine's PreUpdateEventArgs gives them): omnisense/omnibase's EntityHydrator reads the values they replace from them.
PreUpdateArgs::__construct()
public function __construct(object $object, ObjectManager $objectManager, readonly array $changes)PreUpdateArgs::getEntityChangeSet()
public function getEntityChangeSet(): arraySettingListener class
final class SettingListener SettingListener.php:12
The settings' snapshot kept in step on omnibridge/eloquent (plan "omnibase agnostic", step F7c): omnibridge/doctrine's SettingSubscriber, the rule the core's (SettingsInvalidation): a Setting or SettingIntl written empties it.
SettingListener::__construct()
public function __construct(readonly \Closure $settingBag)SettingListener::__invoke()
public function __invoke(object $event): voidStoreMentionees class
final class StoreMentionees implements MentionEnhancerInterface StoreMentionees.php:15
The host's mention enhancer, its mentionees given as the store holds them (plan "omnibase agnostic", step F7c): the enhancer finds the users a text mentions through the host's repositories, which may be another persistence's (a site still on Doctrine beside the store, F7c's proofs); a Mention written by the unit of work must point to the store's user, so each one is read again from the store by its identifier. Everything else is the enhancer's.
StoreMentionees::__construct()
public function __construct(readonly MentionEnhancerInterface $enhancer, readonly EntityStore $store)StoreMentionees::mentions()
public function mentions(): MentionsStoreMentionees::getRepository()
public function getRepository(): MentionsStoreMentionees::extractMentionees()
public function extractMentionees(string|array|null $strOrArray, array $attributes = []): arrayStoreMentionees::enhance()
public function enhance(string|array|null $strOrArray, array $attributes = []): string|array|nullTextOverrideListener class
final class TextOverrideListener TextOverrideListener.php:13
The translations' overrides kept in step on omnibridge/eloquent (plan "omnibase agnostic", step F7c): what omnibase's TextOverrideCacheListener does on Doctrine's events - a TextOverride written, the overriding translator's cache emptied once the flush is done.
TextOverrideListener::__construct()
public function __construct(readonly \Closure $translator)TextOverrideListener::__invoke()
public function __invoke(object $event): voidThreadListener class
final class ThreadListener ThreadListener.php:18
A thread's participants on omnibridge/eloquent (plan "omnibase agnostic", step F7c): omnisense/omnibase's ThreadSubscriber's Doctrine hooks, the rule the core's (ThreadParticipants). A new reply followed by its parent's owners (PrePersist); at OnFlush, the mentions of every thread whose text the flush writes or that it makes publishable, and the followers of a reply moved under another parent (its change set computed again with its collections).
ThreadListener::__construct()
public function __construct(readonly \Closure $mentionEnhancer)ThreadListener::__invoke()
public function __invoke(object $event): voidTrasheableListener class
final class TrasheableListener TrasheableListener.php:23
omnibase's soft delete on omnibridge/eloquent (plan "omnibase agnostic", step F7c): omnibridge/doctrine's TrasheableSubscriber, on the unit of work's OnFlush, the rule the core's (TrashRecorder).
For each #[Trasheable] entity the flush deletes whose deletion field is not stamped yet (an entity stamped already is deleted for real: emptying the trash): the field stamped now, the deletion taken back (persist(), which takes back what it cascades to), the stamp and the entity's other pending changes written by an extra update (no PreUpdate), the entities the removal cascaded to taken back with it, and the trash entry inserted in the same flush. Nothing to evict afterwards: the store keeps no second-level cache.
TrasheableListener::__construct()
public function __construct(string|int $emptyTrash = '+7 days')$emptyTrashbase.extension.empty_trash: a relative date ("+7 days"), or a number of days
TrasheableListener::__invoke()
public function __invoke(object $event): voidVersionableListener class
final class VersionableListener VersionableListener.php:22
omnibase's revisions on omnibridge/eloquent (plan "omnibase agnostic", step F7c): omnibridge/doctrine's VersionableSubscriber, the rule the core's (RevisionRecorder). At OnFlush, each #[Versionable] entity the flush updates, or whose collection it finds changed, gives its anchor (the entity itself, or the translatable of a translation) one Revision of what changed - its versioned fields' changes and its versioned collections' elements before and after -, inserted in the same flush. After the flush, the revisions beyond the most recent ones kept (base.extension.max_revisions) are deleted, in statements.
VersionableListener::__construct()
public function __construct(readonly int $maxRevisions = 5)VersionableListener::__invoke()
public function __invoke(object $event): voidOmnibridge\Eloquent\Omnibase\Repository
ThreadIntlRepository class
class ThreadIntlRepository extends EloquentEntities implements ThreadTranslations ThreadIntlRepository.php:17
omnibridge/doctrine's ThreadIntlRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
ThreadIntlRepository::search()
public function search(array $terms, array $states = [], Thread|int|string|null $parent = null): arrayThreadRepository class
class ThreadRepository extends EloquentEntities implements Threads ThreadRepository.php:17
omnibridge/doctrine's ThreadRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder. getHierarchy() reads the class's #[Hierarchify] (its own, else its nearest parent's).
ThreadRepository::oneBySlug()
public function oneBySlug(string $slug, bool $cached = true): ?ThreadThreadRepository::oneBySlugAndState()
public function oneBySlugAndState(?string $slug, array|string $states, array $orderBy = []): ?ThreadThreadRepository::oneByState()
public function oneByState(array|string $states, array $orderBy = []): ?ThreadThreadRepository::first()
public function first(array $orderBy): ?ThreadThreadRepository::byState()
public function byState(array|string $states, array $orderBy = []): arrayThreadRepository::byStateUncached()
public function byStateUncached(array|string $states): arrayThreadRepository::byStates()
public function byStates(array $states): arrayThreadRepository::oneByParentAndSlugAndState()
public function oneByParentAndSlugAndState(?Thread $parent, string $slug, array|string $states, array $orderBy = []): ?ThreadThreadRepository::byParentAndState()
public function byParentAndState(?Thread $parent, array|string $states, array $orderBy = [], ?int $limit = null, ?int $offset = null): arrayThreadRepository::byParentAndStatePublishedWithin()
public function byParentAndStatePublishedWithin(?Thread $parent, array|string $states, string $within, array $orderBy = []): arrayThreadRepository::oneByStateAndSlugStartingWith()
public function oneByStateAndSlugStartingWith(array|string $states, string $prefix): ?ThreadThreadRepository::countByStatePublishedYoungerThan()
public function countByStatePublishedYoungerThan(array|string $states, int|string $age): intThreadRepository::previousOne()
public function previousOne(array $at, array|string $states, ?string $class = null): ?ThreadThreadRepository::nextOne()
public function nextOne(array $at, array|string $states, ?string $class = null): ?ThreadThreadRepository::countForChildrenIn()
public function countForChildrenIn($thread)The approved children of a thread counted, as omnibridge/doctrine's ThreadRepository::countForChildrenIn() reads its grouped count.
ThreadRepository::cacheByInsensitiveIdentifier()
public function cacheByInsensitiveIdentifier($identifier, array $fields = [])ThreadRepository::findByInsensitiveIdentifier()
public function findByInsensitiveIdentifier($identifier, array $fields = [], $cacheable = false)ThreadRepository::getClassMetadataCompletor()
public function getClassMetadataCompletor(): objectThe class's #[Hierarchify] as HierarchifyTrait reads it from Doctrine's metadata completor: its own, else its nearest parent's.
UserRepository class
class UserRepository extends EloquentEntities implements SecurityUserLoader, SecurityUserProvider, Users UserRepository.php:21
omnibridge/doctrine's UserRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder. Security's user loader, user provider and password upgrader too (step F7d), as Doctrine's declares them through Base\Contract\SecurityUserLoader and SecurityUserProvider (Symfony's interfaces where its security and doctrine-bridge are installed, empty ones elsewhere): what omnibridge/symfony's UserProvider and the entity user provider of a site's security.yaml ask, the same answers; the password written by the unit of work's flush.
UserRepository::supportsClass()
public function supportsClass(string $class): boolUserRepository::loadUserByIdentifier()
public function loadUserByIdentifier(string $identifier): \Symfony\Component\Security\Core\User\UserInterfaceUserRepository::refreshUser()
public function refreshUser(\Symfony\Component\Security\Core\User\UserInterface $user): \Symfony\Component\Security\Core\User\UserInterfaceUserRepository::upgradePassword()
public function upgradePassword(\Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface $user, string $newHashedPassword): voidUserRepository::oneByUsername()
public function oneByUsername(string $username, bool $cached = true): ?UserUserRepository::oneByEmail()
public function oneByEmail(?string $email): ?UserUserRepository::byIds()
public function byIds(array $ids): arrayUserRepository::activeWithin()
public function activeWithin(int $seconds, ?int $exceptId = null): arrayUserRepository::oneById()
public function oneById(int $id): ?UserUserRepository::byRoles()
public function byRoles(array|string $roles): arrayUserRepository::byUsernameContaining()
public function byUsernameContaining(string $term, int $limit = 50): arrayUserRepository::findActiveAdmins()
public function findActiveAdmins(int $onlineDelay, ?int $excludeId = null): arrayUserRepository::cacheByInsensitiveIdentifier()
public function cacheByInsensitiveIdentifier($identifier, array $fields = [])UserRepository::findByInsensitiveIdentifier()
public function findByInsensitiveIdentifier($identifier, array $fields = [], $cacheable = false)Omnibridge\Eloquent\Omnibase\Repository\Analytics
PageViewRepository class
class PageViewRepository extends EloquentEntities implements PageViews PageViewRepository.php:17
omnibridge/doctrine's Analytics\PageViewRepository on Eloquent: countViews() and earliestDate() are finders (sumOf, minOf), compiled by EloquentFinder (step F7b); the upsert and the breakdowns, declared #[BackendOnly] on the interface (no finder: each persistence writes them), are omnibridge/doctrine's SQL sent through Eloquent's connection (step F7f) - ON DUPLICATE KEY UPDATE on MySQL, ON CONFLICT elsewhere, SUM() grouped by DATE() or the hour.
PageViewRepository::incrementView()
public function incrementView(string $path, \DateTimeImmutable $date, string $source = PageView::SOURCE_HUMAN): voidAtomic in the database (two requests the same hour both count), bucketed to the UTC hour, the source part of the unique key - omnibridge/doctrine's statement.
PageViewRepository::countViews()
public function countViews(?string $path = null, ?\DateTimeImmutable $since = null, ?string $source = null): intPageViewRepository::earliestDate()
public function earliestDate(): ?\DateTimeImmutablePageViewRepository::dailyBreakdown()
public function dailyBreakdown(\DateTimeImmutable $since, string|array|null $path = null): arrayPageViewRepository::dailyBreakdownBySource()
public function dailyBreakdownBySource(\DateTimeImmutable $since, string|array|null $path = null): arrayPageViewRepository::hourlyBreakdown()
public function hourlyBreakdown(\DateTimeImmutable $since, string|array|null $path = null): arrayPageViewRepository::hourlyBreakdownBySource()
public function hourlyBreakdownBySource(\DateTimeImmutable $since, string|array|null $path = null): arrayPageVisitRepository class
class PageVisitRepository extends EloquentEntities implements PageVisits PageVisitRepository.php:17
omnibridge/doctrine's Analytics\PageVisitRepository on Eloquent (step F7f): its four methods, declared #[BackendOnly] on the interface (no finder: each persistence writes them), are omnibridge/doctrine's SQL sent through Eloquent's connection - INSERT IGNORE (ON CONFLICT DO NOTHING off MySQL), COUNT(*) over a DISTINCT subquery, grouped by DATE() or the hour. The plain reads (find, findBy, count, the finders) are EloquentEntities'.
PageVisitRepository::recordPresence()
public function recordPresence(string $path, string $subjectType, string $subjectId, \DateTimeImmutable $date): voidPageVisitRepository::countUnique()
public function countUnique(?\DateTimeImmutable $since = null, string|array|null $path = null): intPageVisitRepository::dailyBreakdown()
public function dailyBreakdown(\DateTimeImmutable $since, string|array|null $path = null): arrayPageVisitRepository::hourlyBreakdown()
public function hourlyBreakdown(\DateTimeImmutable $since, string|array|null $path = null): arrayVisitRepository class
class VisitRepository extends EloquentEntities implements Visits VisitRepository.php:17
omnibridge/doctrine's Analytics\VisitRepository on Eloquent: countUnique() is a finder (distinctCountFor...), compiled by EloquentFinder (step F7b); the INSERT IGNORE, the retention and the breakdowns, declared #[BackendOnly] on the interface (no finder: each persistence writes them), are omnibridge/doctrine's SQL sent through Eloquent's connection (step F7f).
VisitRepository::recordPresence()
public function recordPresence(string $subjectType, string $subjectId, \DateTimeImmutable $date): voidVisitRepository::insertIgnore()
public static function insertIgnore(bool $onMySql, string $into): string"INSERT IGNORE INTO $into" on MySQL and MariaDB, "INSERT INTO $into ON CONFLICT DO NOTHING" elsewhere.
VisitRepository::countUnique()
public function countUnique(string $subjectType, ?\DateTimeImmutable $since = null): intVisitRepository::returning()
public function returning(string $subjectType, \DateTimeImmutable $previousSince, \DateTimeImmutable $currentSince): arrayVisitRepository::dailyBreakdown()
public function dailyBreakdown(string $subjectType, \DateTimeImmutable $since): arrayVisitRepository::hourlyBreakdown()
public function hourlyBreakdown(string $subjectType, \DateTimeImmutable $since): arrayOmnibridge\Eloquent\Omnibase\Repository\Extension
RevisionRepository class
class RevisionRepository extends EloquentEntities implements Revisions RevisionRepository.php:15
omnibridge/doctrine's Extension\RevisionRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
RevisionRepository::history()
public function history(string $entityClass, int $entityId, ?int $limit = null): arrayRevisionRepository::obsoleteIds()
public function obsoleteIds(string $entityClass, int $entityId, int $keep): array- Returns
the revisions past the $keep newest, a thousand at most
TrashBallRepository class
class TrashBallRepository extends EloquentEntities implements TrashBalls TrashBallRepository.php:15
omnibridge/doctrine's Extension\TrashBallRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
TrashBallRepository::contents()
public function contents(?string $entityClass = null, ?int $limit = null, int $offset = 0): arrayTrashBallRepository::countContents()
public function countContents(?string $entityClass = null): intTrashBallRepository::expired()
public function expired(?\DateTimeInterface $now = null, ?int $limit = null): arrayTrashBallRepository::forEntity()
public function forEntity(string $entityClass, int $entityId): ?TrashBallOmnibridge\Eloquent\Omnibase\Repository\Hours
ScopedWeekRepository class
class ScopedWeekRepository extends EloquentEntities implements ScopedWeeks ScopedWeekRepository.php:15
omnibridge/doctrine's Hours\ScopedWeekRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder, the writes through the unit of work (step F7c).
ScopedWeekRepository::ofScope()
public function ofScope(string $scope): ?ScopedWeekScopedWeekRepository::week()
public function week(string $scope): ?arrayScopedWeekRepository::save()
public function save(string $scope, array $week): ScopedWeekScopedWeekRepository::forget()
public function forget(string $scope): voidSpecialDayRepository class
class SpecialDayRepository extends EloquentEntities implements SpecialDays SpecialDayRepository.php:15
omnibridge/doctrine's Hours\SpecialDayRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
SpecialDayRepository::upcoming()
public function upcoming(\DateTimeInterface $from, int $limit = 50, ?string $scope = null): arrayWeekDayHoursRepository class
class WeekDayHoursRepository extends EloquentEntities implements WeekDays WeekDayHoursRepository.php:15
omnibridge/doctrine's Hours\WeekDayHoursRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder, the writes through the unit of work (step F7c).
WeekDayHoursRepository::week()
public function week(): arrayWeekDayHoursRepository::save()
public function save(array $week): voidOmnibridge\Eloquent\Omnibase\Repository\Layout
ImageCropRepository class
class ImageCropRepository extends EloquentEntities implements ImageCrops ImageCropRepository.php:15
omnibridge/doctrine's Layout\ImageCropRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
ImageCropRepository::oneBySlugOfImage()
public function oneBySlugOfImage(string $slug, string $source): ?ImageCropImageCropRepository::oneClosestToRatio()
public function oneClosestToRatio(float|int $ratio0, string $source): ?ImageCropImageCropRepository::oneClosestToRatioAndSize()
public function oneClosestToRatioAndSize(float|int $ratio0, float|int $width0, float|int $height0, string $source): ?ImageCropRedirectionRepository class
class RedirectionRepository extends EloquentEntities implements Redirections RedirectionRepository.php:15
omnibridge/doctrine's Layout\RedirectionRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder; hit(), declared #[BackendOnly] on the interface (no finder), one UPDATE on Eloquent's connection (F7f).
RedirectionRepository::forAddress()
public function forAddress(string $address): ?RedirectionRedirectionRepository::hit()
public function hit(Redirection $redirection): voidomnibridge/doctrine's bulk DQL UPDATE as one statement on the row (step F7f): hits = hits + 1 in the database, atomic under concurrent requests, and the moment of the hit; the entity in memory is left as it was read, as a DQL UPDATE leaves it.
SemanticRepository class
class SemanticRepository extends EloquentEntities implements Semantics SemanticRepository.php:15
omnibridge/doctrine's Layout\SemanticRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
SemanticRepository::every()
public function every(): arraySettingRepository class
class SettingRepository extends EloquentEntities implements Settings SettingRepository.php:15
omnibridge/doctrine's Layout\SettingRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
SettingRepository::under()
public function under(?string $path, bool $linkedBagOnly = false, bool $cached = true): arraySettingRepository::oneByInsensitivePath()
public function oneByInsensitivePath(string $path): ?SettingTextOverrideRepository class
class TextOverrideRepository extends EloquentEntities TextOverrideRepository.php:14
omnibridge/doctrine's Layout\TextOverrideRepository on Eloquent (plan "omnibase agnostic", step F7b): no interface of the core's names it, but omnibase's OverridingTranslator calls its map().
TextOverrideRepository::map()
public function map(): array- Returns
"domain|locale|key" => the text
WidgetRepository class
class WidgetRepository extends EloquentEntities implements Widgets WidgetRepository.php:15
omnibridge/doctrine's Layout\WidgetRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
WidgetRepository::oneByPath()
public function oneByPath(string $path, bool $cached = true): ?WidgetWidgetRepository::every()
public function every(bool $cached = true): arrayOmnibridge\Eloquent\Omnibase\Repository\Layout\Widget
SlotRepository class
class SlotRepository extends WidgetRepository implements Slots SlotRepository.php:15
omnibridge/doctrine's Layout\Widget\SlotRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
SlotRepository::oneByPath()
public function oneByPath(string $path, bool $cached = true): ?SlotOmnibridge\Eloquent\Omnibase\Repository\Thread
CommentRepository class
class CommentRepository extends EloquentEntities implements Comments CommentRepository.php:18
omnibridge/doctrine's Thread\CommentRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
CommentRepository::findVisible()
public function findVisible(?Thread $thread, int $limit = 200): arrayCommentRepository::countVisible()
public function countVisible(?Thread $thread): intCommentRepository::countPending()
public function countPending(): intCommentRepository::findPending()
public function findPending(int $limit = 20): arrayCommentRepository::findLastFromIp()
public function findLastFromIp(string $ip): ?CommentLikeRepository class
class LikeRepository extends EloquentEntities implements Likes LikeRepository.php:17
omnibridge/doctrine's Thread\LikeRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
LikeRepository::oneByThreadAndUser()
public function oneByThreadAndUser(Thread $thread, ?User $user): ?LikeMentionRepository class
class MentionRepository extends EloquentEntities implements Mentions MentionRepository.php:16
omnibridge/doctrine's Thread\MentionRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
MentionRepository::byThread()
public function byThread(Thread $thread): arrayTagRepository class
class TagRepository extends EloquentEntities implements Tags TagRepository.php:15
omnibridge/doctrine's Thread\TagRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
TagRepository::oneBySlug()
public function oneBySlug(string $slug): ?TagTagRepository::bySlugs()
public function bySlugs(array $slugs): arrayTagRepository::cacheByInsensitiveIdentifier()
public function cacheByInsensitiveIdentifier($identifier, array $fields = [])TagRepository::findByInsensitiveIdentifier()
public function findByInsensitiveIdentifier($identifier, array $fields = [], $cacheable = false)Omnibridge\Eloquent\Omnibase\Repository\User
ComplaintRepository class
class ComplaintRepository extends EloquentEntities implements Complaints ComplaintRepository.php:15
omnibridge/doctrine's User\ComplaintRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
ComplaintRepository::newest()
public function newest(?string $status = null, ?string $source = null, int $limit = 200): arrayConnectionRepository class
class ConnectionRepository extends EloquentEntities implements Connections ConnectionRepository.php:16
omnibridge/doctrine's User\ConnectionRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
ConnectionRepository::oneByUniqidAndUser()
public function oneByUniqidAndUser(string $uniqid, User $user): ?ConnectionConnectionRepository::countFor()
public function countFor(User $user): intIdentityRepository class
class IdentityRepository extends EloquentEntities implements Identities IdentityRepository.php:15
omnibridge/doctrine's User\IdentityRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
IdentityRepository::findOneBySubject()
public function findOneBySubject(string $provider, string $subject): ?IdentityIdentityRepository::findOfUser()
public function findOfUser(object $user): arrayNotificationRepository class
class NotificationRepository extends EloquentEntities implements Notifications NotificationRepository.php:17
omnibridge/doctrine's User\NotificationRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
NotificationRepository::countUnreadFor()
public function countUnreadFor(User $user): intNotificationRepository::findVisibleFor()
public function findVisibleFor(User $user, int $limit = 100, int $offset = 0, bool $unreadOnly = false): arrayPasskeyRepository class
class PasskeyRepository extends EloquentEntities implements Passkeys, PasskeyRecords PasskeyRepository.php:22
The passkeys on the store (plan "omnibase agnostic", steps F7b and F7c): the core's Passkeys, and PasskeyRecords - webauthn-symfony-bundle's credential repository where it is installed (CredentialRecordRepositoryInterface and CanSaveCredentialRecord), an interface that asks nothing elsewhere - as omnibridge/doctrine's PasskeyRepository answers them: a credential found by its identifier, a user's credentials, a credential saved through the unit of work (the passkey's counters updated, or a new passkey of the user its handle names).
PasskeyRepository::findOneByCredential()
public function findOneByCredential(string $publicKeyCredentialId): ?PasskeyPasskeyRepository::findAllForUserEntity()
public function findAllForUserEntity(PublicKeyCredentialUserEntity $publicKeyCredentialUserEntity): arrayPasskeyRepository::findOneByCredentialId()
public function findOneByCredentialId(string $publicKeyCredentialId): ?CredentialRecordPasskeyRepository::saveCredentialRecord()
public function saveCredentialRecord(CredentialRecord $credentialRecord): voidPasskeyRepository::credentialRecord()
public static function credentialRecord(Passkey $passkey): CredentialRecordPasskeyRepository::fill()
public static function fill(Passkey $passkey, CredentialRecord $record): PasskeyPushSubscriptionRepository class
class PushSubscriptionRepository extends EloquentEntities implements PushSubscriptions PushSubscriptionRepository.php:15
omnibridge/doctrine's User\PushSubscriptionRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
PushSubscriptionRepository::countDistinctUsers()
public function countDistinctUsers(): intTokenRepository class
class TokenRepository extends EloquentEntities implements Tokens TokenRepository.php:15
omnibridge/doctrine's User\TokenRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.
TokenRepository::oneByValueAndName()
public function oneByValueAndName(?string $value, string $name): ?TokenTokenRepository::oneByValue()
public function oneByValue(?string $value): ?TokenTokenRepository::oneSigningInByNameAndValue()
public function oneSigningInByNameAndValue(string $name, ?string $value): ?TokenTokenRepository::oneSigningInByValue()
public function oneSigningInByValue(?string $value): ?Token