Skip to content

omnibridge/eloquent API reference

Floor
Bridge
Version
1.x
Verified for real
Its README does not say
Licence
MIT
composer require omnibridge/eloquent:1.x-dev

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.

Omnibridge\Eloquent

  • Cascades class

    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).

    4 methods

  • Casts class

    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.

    7 methods

  • CommitOrder class

    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).

    4 methods

  • Connections class

    Eloquent's database connection, with a framework or without one: the store (EntityStore) reads through an Illuminate\Database\Connection, whoever made it.

    5 methods

  • Container class

    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).

    2 methods

  • EloquentUnitOfWork class

    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.

    35 methods

  • EntityMap class

    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.

    12 methods · 6 properties

  • EntityNotFound class

    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.

    1 method

  • EntityStore class

    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.

    33 methods

  • IdentityMap class

    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.

    9 methods

  • InvalidPersistence class

    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.

    5 methods

  • LazyCollection class

    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.

    16 methods

  • Mapping class

    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).

    4 methods · 1 property

  • Persister class

    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).

    7 methods

  • UnsupportedPersistence class

    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.

    4 methods

Omnibridge\Eloquent\Omnibase

  • AttributeRelay class

    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()).

    4 methods

  • EloquentBackend class

    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.

    7 methods

  • EloquentBehaviours class

    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).

    4 methods · 1 constant

  • EloquentEntities class

    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()).

    16 methods

  • EloquentPersistence class

    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.

    9 methods · 1 constant

  • EloquentRepositories class

    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.

    7 methods · 1 constant

  • OmnibaseCascades class

    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).

    1 method

  • OmnibaseCasts class

    omnibase's column types read as omnibridge/doctrine's DBAL types read them (plan "omnibase agnostic", step F7b):

    1 method

Omnibridge\Eloquent\Omnibase\Behaviour

  • EloquentBulkDeletes class

    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.

    3 methods

  • EloquentCacheBackend class

    #[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

  • EloquentColumnTypes class

    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.

    2 methods

  • EloquentConditionalUpdates class

    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.

    2 methods

  • EloquentEntityCache class

    EntityCache on omnibridge/eloquent (plan "omnibase agnostic", step F7c): the store keeps no second-level cache.

    4 methods

  • EloquentOrderColumnBackend class

    #[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

  • EloquentRowLocks class

    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).

    2 methods

  • EloquentSlugifyBackend class

    #[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

  • EloquentVaultBackend class

    #[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

  • EloquentFinder class

    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):

    6 methods

  • EntitySubject class

    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).

    11 methods

  • FinderQuery class

    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.

    11 methods

Omnibridge\Eloquent\Omnibase\Lifecycle

  • DemoAccountLockListener class

    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.

    3 methods

  • EloquentObjectManager class

    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).

    15 methods

  • EntityDispatcherListener class

    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.

    4 methods

  • EntityDispatchersListener class

    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.

    4 methods

  • IntlListener class

    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).

    1 method

  • OmnibaseListeners class

    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).

    3 methods

  • PreFlushListener class

    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).

    2 methods

  • PreUpdateArgs class

    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.

    2 methods

  • SettingListener class

    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.

    2 methods

  • StoreMentionees class

    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.

    5 methods

  • TextOverrideListener class

    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.

    2 methods

  • ThreadListener class

    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).

    2 methods

  • TrasheableListener class

    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).

    2 methods

  • VersionableListener class

    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.

    2 methods

Omnibridge\Eloquent\Omnibase\Repository

  • ThreadIntlRepository class

    omnibridge/doctrine's ThreadIntlRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.

    1 method

  • ThreadRepository class

    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).

    18 methods

  • UserRepository class

    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.

    14 methods

Omnibridge\Eloquent\Omnibase\Repository\Analytics

  • PageViewRepository class

    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.

    7 methods

  • PageVisitRepository class

    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'.

    4 methods

  • VisitRepository class

    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).

    6 methods

Omnibridge\Eloquent\Omnibase\Repository\Extension

  • RevisionRepository class

    omnibridge/doctrine's Extension\RevisionRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.

    2 methods

  • TrashBallRepository class

    omnibridge/doctrine's Extension\TrashBallRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.

    4 methods

Omnibridge\Eloquent\Omnibase\Repository\Hours

  • ScopedWeekRepository class

    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).

    4 methods

  • SpecialDayRepository class

    omnibridge/doctrine's Hours\SpecialDayRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.

    1 method

  • WeekDayHoursRepository class

    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).

    2 methods

Omnibridge\Eloquent\Omnibase\Repository\Layout

  • ImageCropRepository class

    omnibridge/doctrine's Layout\ImageCropRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.

    3 methods

  • RedirectionRepository class

    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).

    2 methods

  • SemanticRepository class

    omnibridge/doctrine's Layout\SemanticRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.

    1 method

  • SettingRepository class

    omnibridge/doctrine's Layout\SettingRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.

    2 methods

  • TextOverrideRepository class

    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().

    1 method

  • WidgetRepository class

    omnibridge/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

  • SlotRepository class

    omnibridge/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

  • CommentRepository class

    omnibridge/doctrine's Thread\CommentRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.

    5 methods

  • LikeRepository class

    omnibridge/doctrine's Thread\LikeRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.

    1 method

  • MentionRepository class

    omnibridge/doctrine's Thread\MentionRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.

    1 method

  • TagRepository class

    omnibridge/doctrine's Thread\TagRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.

    4 methods

Omnibridge\Eloquent\Omnibase\Repository\User

  • ComplaintRepository class

    omnibridge/doctrine's User\ComplaintRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.

    1 method

  • ConnectionRepository class

    omnibridge/doctrine's User\ConnectionRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.

    2 methods

  • IdentityRepository class

    omnibridge/doctrine's User\IdentityRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.

    2 methods

  • NotificationRepository class

    omnibridge/doctrine's User\NotificationRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.

    2 methods

  • PasskeyRepository class

    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).

    6 methods

  • PushSubscriptionRepository class

    omnibridge/doctrine's User\PushSubscriptionRepository on Eloquent (plan "omnibase agnostic", step F7b): the same finders, compiled by EloquentFinder.

    1 method

  • TokenRepository class

    omnibridge/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): void

A 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): bool

Whether 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): bool

Whether 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): self

The 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): self

The same conversions, plus a type of the application's own (or one replaced).

$toPhp

the column's value (never null) => the entity's

$toDatabase

the entity's value (never null) => the column's; the value as it is without

$readsNull

whether $toPhp is given null too (a set reads NULL as no value: [])

Casts::columnTypes()

public function columnTypes(): ?ColumnTypes

Casts::knows()

public function knows(string $type): bool

Whether 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): mixed

The column's value as the entity holds it.

Casts::toDatabase()

public function toDatabase(string $type, mixed $value): mixed

The 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): void

CommitOrder::has()

public function has(object $node): bool

CommitOrder::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(): array

Connections 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'): Connection

A connection made by Capsule, Eloquent's manager outside Laravel.

$config

Illuminate's configuration of a connection (driver, host, database, username...)

Connections::url()

public static function url(string $url, string $name = 'default'): Connection

A 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): array

The configuration array of a database URL (url()).

Connections::pdo()

public static function pdo(\PDO $pdo, string $database = ''): Connection

A 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): Connection

The 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(): array

The 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(): EntityStore

EloquentUnitOfWork::cascades()

public function cascades(): Cascades

EloquentUnitOfWork::listen()

public function listen(\Closure $listener): void

A listener of the Lifecycle events (PrePersist ... PostFlush, PostLoad), called before the PSR-14 dispatcher.

EloquentUnitOfWork::persist()

public function persist(object $entity): void

EloquentUnitOfWork::remove()

public function remove(object $entity): void

EloquentUnitOfWork::flush()

public function flush(): void

EloquentUnitOfWork::refresh()

public function refresh(object $entity): void

EloquentUnitOfWork::contains()

public function contains(object $entity): bool

EloquentUnitOfWork::reference()

public function reference(string $class, mixed $id): object

EloquentUnitOfWork::transactional()

public function transactional(callable $work): mixed

EloquentUnitOfWork::isNew()

public function isNew(object $entity): bool

EloquentUnitOfWork::identifier()

public function identifier(object $entity): mixed

EloquentUnitOfWork::className()

public function className(object $entity): string

EloquentUnitOfWork::original()

public function original(object $entity): array

EloquentUnitOfWork::changes()

public function changes(object $entity): array

EloquentUnitOfWork::recompute()

public function recompute(object $entity): void

Doctrine'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): bool

Whether the entity is scheduled for insertion (persisted, not flushed).

EloquentUnitOfWork::isScheduledForDelete()

public function isScheduledForDelete(object $entity): bool

Whether 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): void

An 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): void

The 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): void

The 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): void

A 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): void

What the unit of work remembers of one property, moved forward (Doctrine's setOriginalEntityProperty()).

EloquentUnitOfWork::scheduledCollectionUpdates()

public function scheduledCollectionUpdates(): array

The 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): void

The entity removed at the next flush as an orphan (Doctrine's scheduleOrphanRemoval()).

EloquentUnitOfWork::cancelOrphanRemoval()

public function cancelOrphanRemoval(object $entity): void

An orphan removal taken back (Doctrine's cancelOrphanRemoval()).

EloquentUnitOfWork::recomputeWithAssociations()

public function recomputeWithAssociations(object $entity): void

The 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): void

The 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(): void

Everything 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): bool

Whether the entity is a lazy object not read yet (Doctrine's isUninitializedObject()).

EloquentUnitOfWork::cancelDeletion()

public function cancelDeletion(object $entity): void

A 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 $tables
public readonly array $identifier
public readonly string $root
public readonly ?Inheritance $inheritance
public readonly Description $description
public readonly Entity $entity

EntityMap::__construct()

public function __construct(public readonly Description $description, public readonly Entity $entity)

EntityMap::className()

public function className(): string

EntityMap::alias()

public function alias(string $table, string $prefix = 't'): string

The 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): string

The 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): bool

Whether 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): string

The 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(): ?string

The discriminator's column in the root's table, null without inheritance.

EntityMap::discriminatorValues()

public function discriminatorValues(): ?array

The 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): string

The class a row is, by its discriminator (the class itself without inheritance).

EntityMap::hasSubclasses()

public function hasSubclasses(): bool

Whether 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): self

EntityStore 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(): Connection

EntityStore::mapping()

public function mapping(): Mapping

EntityStore::casts()

public function casts(): Casts

EntityStore::identityMap()

public function identityMap(): IdentityMap

EntityStore::queries()

public function queries(): int

How 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): void

A 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): void

EntityStore::hasCondition()

public function hasCondition(string $name): bool

EntityStore::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(): void

Forgets every entity read: the next read makes new objects.

EntityStore::onLoad()

public function onLoad(\Closure $listener): void

A 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): array

The 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): bool

Whether the store holds what the entity was (it read it, or the unit of work wrote it).

EntityStore::originalCollections()

public function originalCollections(object $entity): array

The to-many collections of the entity as read or last flushed (the collection objects).

EntityStore::snapshot()

public function snapshot(object $entity): void

What the entity holds now becomes what it was: after a flush wrote it.

EntityStore::setOriginal()

public function setOriginal(object $entity, string $property, mixed $value): void

Overwrites the remembered value of one property (Doctrine's setOriginalEntityProperty()).

EntityStore::value()

public function value(object $entity, string $property): mixed

The 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): void

Writes a field or an association of the entity, as Doctrine writes it (no setter).

EntityStore::register()

public function register(object $entity, mixed $id): void

The entity kept in the identity map under that identifier (a new entity once its row is written).

EntityStore::forget()

public function forget(object $entity): void

The entity out of the identity map and its remembered values forgotten (its row deleted).

EntityStore::find()

public function find(string $class, mixed $id): ?object

The 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): array

The entities of those identifiers, in the order given, those not found left out.

EntityStore::reference()

public function reference(string $class, mixed $id): ?object

The 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): array

The 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): Builder

The 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): void

The 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): array

The 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): array

The 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): array

The entities of rows read by rows(): each of its class, through the identity map.

EntityStore::refresh()

public function refresh(object $entity): bool

The entity read again from its row, its unsaved changes lost; false when its row is gone.

EntityStore::identifier()

public function identifier(object $entity): mixed

The entity's identifier: its value, or property => value for a composite one; read without loading a ghost.

EntityStore::isUninitialized()

public function isUninitialized(object $entity): bool

Whether 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): string

The key of an identifier: its value, or its values joined for a composite one.

IdentityMap::get()

public function get(string $root, mixed $id): ?object

IdentityMap::add()

public function add(string $root, mixed $id, object $entity): void

IdentityMap::contains()

public function contains(object $entity): bool

IdentityMap::remove()

public function remove(object $entity): void

IdentityMap::all()

public function all(): array

Every entity kept, by root class in the order the classes were first met, then in the order kept.

IdentityMap::count()

public function count(): int

IdentityMap::clear()

public function clear(): void

InvalidPersistence 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): self

InvalidPersistence::cycle()

public static function cycle(array $entities): self

InvalidPersistence::notEntity()

public static function notEntity(object $entity): self

InvalidPersistence::notManaged()

public static function notManaged(object $entity, string $operation): self

InvalidPersistence::invalidAssociation()

public static function invalidAssociation(string $class, string $property, mixed $value): self

LazyCollection 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)
$owning

the 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): self

A 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(): array

As 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): void

LazyCollection::snapshot()

public function snapshot(): array

The elements as read or last flushed (read now if the collection was not).

LazyCollection::takeSnapshot()

public function takeSnapshot(): void

What it holds now becomes its snapshot (a flush wrote it).

LazyCollection::wasCleared()

public function wasCleared(): bool

LazyCollection::isDirty()

public function isDirty(): bool

LazyCollection::wrap()

public function wrap(\Closure $wrap): void

The 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): void

An 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): mixed

LazyCollection::removeElement()

public function removeElement(mixed $element): bool

LazyCollection::set()

public function set(string|int $key, mixed $value): void

LazyCollection::clear()

public function clear(): void

LazyCollection::offsetSet()

public function offsetSet(mixed $offset, mixed $value): void

LazyCollection::offsetUnset()

public function offsetUnset(mixed $offset): void

Mapping 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): EntityMap

Mapping::has()

public function has(string $class): bool

Mapping::classes()

public function classes(): array

The 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): array

Inserts 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.

$changeSet

property => [before, after]

$pending

whether 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): void

Updates 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): void

Deletes 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): array

The 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): void

Rows 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): bool

Whether 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): self

UnsupportedPersistence::composite()

public static function composite(string $class, string $what): self

UnsupportedPersistence::closed()

public static function closed(): self

UnsupportedPersistence::operation()

public static function operation(string $operation, string $why): self

Omnibridge\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)
$attributeReader

a 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): self

The relay listening to the unit of work's events.

AttributeRelay::attributeReader()

public function attributeReader(): AttributeReader

The reader the behaviours are read with: the one given, or the host's, asked once.

AttributeRelay::__invoke()

public function __invoke(object $event): void

EloquentBackend 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 = [])
$scopes

more scopes than omnibase's trash and vault

EloquentBackend::name()

public function name(): string

EloquentBackend::supports()

public function supports(string $feature): bool

EloquentBackend::unitOfWork()

public function unitOfWork(): UnitOfWork

EloquentBackend::enableScope()

public function enableScope(string $name, array $parameters = []): void

EloquentBackend::disableScope()

public function disableScope(string $name): void

EloquentBackend::isScopeEnabled()

public function isScopeEnabled(string $name): bool

EloquentBehaviours 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(): void

EloquentBehaviours::ensureRegistered()

public static function ensureRegistered(): void

EloquentBehaviours::remember()

public static function remember(EloquentPersistence $persistence): void

The 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): ?EloquentPersistence

EloquentEntities 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(): EloquentUnitOfWork

The unit of work the repository writes through (refused when it was made without one).

EloquentEntities::getClassName()

public function getClassName(): string

The class the repository reads (its rows: of it and its subclasses).

EloquentEntities::entityMap()

public function entityMap(): EntityMap

The class's tables and columns (EntityMap).

EloquentEntities::finder()

public function finder(): EloquentFinder

EloquentEntities::__call()

public function __call(string $method, array $arguments): mixed

The finder language: findBy...(), findOneBy...(), cache...(), count...(), lengthOf...(), sumOf...().

..

EloquentEntities::find()

public function find($id): ?object

EloquentEntities::findAll()

public function findAll(): array

EloquentEntities::findBy()

public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array

EloquentEntities::findOneBy()

public function findOneBy(array $criteria, ?array $orderBy = null): ?object

EloquentEntities::count()

public function count(array $criteria = []): int

EloquentEntities::findByExample()

public function findByExample(object $select, ?array $orderBy = null, $limit = null, $offset = null): array

Query-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): array

EloquentEntities::persist()

public function persist($entity, bool $flush = false): void

EloquentEntities::remove()

public function remove($entity, bool $flush = false): void

EloquentEntities::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): self

EloquentPersistence::host()

public static function host(Connection $connection, ContainerInterface $services, array $options = [], ?Description $description = null): self

omnibase'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): self

omnibase'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(): void

Between 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(): ?OmnibaseListeners

The behaviours' relay and the listeners' adapters attached by the option "lifecycle" (null without it).

EloquentPersistence::store()

public function store(): EntityStore

EloquentPersistence::unitOfWork()

public function unitOfWork(): EloquentUnitOfWork

EloquentPersistence::backend()

public function backend(): EloquentBackend

EloquentPersistence::repositories()

public function repositories(): EloquentRepositories

EloquentRepositories 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): void

An 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): Entities

EloquentRepositories::implementing()

public function implementing(string $interface, ?string $class = null): Entities

The 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).

$class

the entity to read, the interface's own by default

EloquentRepositories::repositoryClass()

public function repositoryClass(string $class): string

EloquentRepositories::byIds()

public function byIds(string $class, array $ids): array

EloquentRepositories::oneById()

public function oneById(string $class, mixed $id): ?object

OmnibaseCascades 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(): \Closure

OmnibaseCasts 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
$options

EntitySchema'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): int

EloquentBulkDeletes::deleteIds()

public function deleteIds(string $class, array $ids): int

The 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): void

EloquentColumnTypes 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): bool

EloquentConditionalUpdates 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): bool

EloquentEntityCache 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(): bool

EloquentEntityCache::evict()

public function evict(string $class, mixed $id): void

EloquentEntityCache::evictClass()

public function evictClass(string $class): void

EloquentOrderColumnBackend 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): bool

EloquentRowLocks 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): mixed

EloquentSlugifyBackend 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(): array

EloquentSlugifyBackend::uniqueAlone()

public function uniqueAlone(string $class, string $property): bool

EloquentVaultBackend 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): void

Omnibridge\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)
$routeParameters

a host's request => its route parameters (WithRoute), false for anything else

EloquentFinder::subject()

public function subject(): EntitySubject

EloquentFinder::read()

public function read(string $method, array $arguments): Query

Reads 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): mixed

Reads a finder's name and arguments, then compiles and runs it.

EloquentFinder::execute()

public function execute(Query $query): mixed

Compiles 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|false

A 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(): EntityMap

EntitySubject::getClassName()

public function getClassName(): string

EntitySubject::getFieldNames()

public function getFieldNames(): array

EntitySubject::hasField()

public function hasField(string $name): bool

EntitySubject::isField()

public function isField(string $name): bool

EntitySubject::isAssociation()

public function isAssociation(string $name): bool

EntitySubject::relation()

public function relation(string $name): ?Relation

EntitySubject::typeOf()

public function typeOf(string $path, \Closure $mapOf): ?string

The 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): ?string

The 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): array

FinderQuery 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)
$columns

a mixed result's key => the column it is read from

FinderQuery::getResult()

public function getResult(): array

FinderQuery::getOneOrNullResult()

public function getOneOrNullResult(): mixed

The first result, null without one; more than one refused, as Doctrine's NonUniqueResultException does.

FinderQuery::getSQL()

public function getSQL(): string

The 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(): int

FinderQuery::getMaxResults()

public function getMaxResults(): ?int

FinderQuery::builder()

public function builder(): Builder

FinderQuery::count()

public function count(): int

The 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): array

One 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(): \ArrayIterator

Omnibridge\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)
$lock

a 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): void

DemoAccountLockListener::reset()

public function reset(): void

EloquentObjectManager 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(): EloquentUnitOfWork

EloquentObjectManager::find()

public function find(string $className, mixed $id): ?object

EloquentObjectManager::persist()

public function persist(object $object): void

EloquentObjectManager::remove()

public function remove(object $object): void

EloquentObjectManager::clear()

public function clear(): void

EloquentObjectManager::detach()

public function detach(object $object): void

EloquentObjectManager::refresh()

public function refresh(object $object): void

EloquentObjectManager::flush()

public function flush(): void

EloquentObjectManager::getRepository()

public function getRepository(string $className): ObjectRepository

EloquentObjectManager::getClassMetadata()

public function getClassMetadata(string $className): ClassMetadata

EloquentObjectManager::getMetadataFactory()

public function getMetadataFactory(): ClassMetadataFactory

EloquentObjectManager::initializeObject()

public function initializeObject(object $obj): void

EloquentObjectManager::isUninitializedObject()

public function isUninitializedObject(mixed $value): bool

EloquentObjectManager::contains()

public function contains(object $object): bool

EntityDispatcherListener 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(): AbstractEventDispatcher

EntityDispatcherListener::former()

public function former(): bool

Whether the dispatcher is called with doctrine/persistence's LifecycleEventArgs (a former hook overridden).

EntityDispatcherListener::__invoke()

public function __invoke(object $event): void

EntityDispatchersListener 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): void

EntityDispatchersListener::listeners()

public function listeners(): array
Returns

one per dispatcher, in their order

EntityDispatchersListener::dispatchers()

public function dispatchers(): array

IntlListener 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): void

OmnibaseListeners 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 = []): self

OmnibaseListeners::listeners()

public function listeners(): array
Returns

the relay and the adapters, in the order they listen

OmnibaseListeners::get()

public function get(string $class): ?object

The 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)
$service

a service with a preFlush() taking no argument

PreFlushListener::__invoke()

public function __invoke(object $event): void

PreUpdateArgs 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(): array

SettingListener 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): void

StoreMentionees 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(): Mentions

StoreMentionees::getRepository()

public function getRepository(): Mentions

StoreMentionees::extractMentionees()

public function extractMentionees(string|array|null $strOrArray, array $attributes = []): array

StoreMentionees::enhance()

public function enhance(string|array|null $strOrArray, array $attributes = []): string|array|null

TextOverrideListener 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): void

ThreadListener 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): void

TrasheableListener 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')
$emptyTrash

base.extension.empty_trash: a relative date ("+7 days"), or a number of days

TrasheableListener::__invoke()

public function __invoke(object $event): void

VersionableListener 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): void

Omnibridge\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.

public function search(array $terms, array $states = [], Thread|int|string|null $parent = null): array

ThreadRepository 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): ?Thread

ThreadRepository::oneBySlugAndState()

public function oneBySlugAndState(?string $slug, array|string $states, array $orderBy = []): ?Thread

ThreadRepository::oneByState()

public function oneByState(array|string $states, array $orderBy = []): ?Thread

ThreadRepository::first()

public function first(array $orderBy): ?Thread

ThreadRepository::byState()

public function byState(array|string $states, array $orderBy = []): array

ThreadRepository::byStateUncached()

public function byStateUncached(array|string $states): array

ThreadRepository::byStates()

public function byStates(array $states): array

ThreadRepository::oneByParentAndSlugAndState()

public function oneByParentAndSlugAndState(?Thread $parent, string $slug, array|string $states, array $orderBy = []): ?Thread

ThreadRepository::byParentAndState()

public function byParentAndState(?Thread $parent, array|string $states, array $orderBy = [], ?int $limit = null, ?int $offset = null): array

ThreadRepository::byParentAndStatePublishedWithin()

public function byParentAndStatePublishedWithin(?Thread $parent, array|string $states, string $within, array $orderBy = []): array

ThreadRepository::oneByStateAndSlugStartingWith()

public function oneByStateAndSlugStartingWith(array|string $states, string $prefix): ?Thread

ThreadRepository::countByStatePublishedYoungerThan()

public function countByStatePublishedYoungerThan(array|string $states, int|string $age): int

ThreadRepository::previousOne()

public function previousOne(array $at, array|string $states, ?string $class = null): ?Thread

ThreadRepository::nextOne()

public function nextOne(array $at, array|string $states, ?string $class = null): ?Thread

ThreadRepository::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(): object

The 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): bool

UserRepository::loadUserByIdentifier()

public function loadUserByIdentifier(string $identifier): \Symfony\Component\Security\Core\User\UserInterface

UserRepository::refreshUser()

public function refreshUser(\Symfony\Component\Security\Core\User\UserInterface $user): \Symfony\Component\Security\Core\User\UserInterface

UserRepository::upgradePassword()

public function upgradePassword(\Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void

UserRepository::oneByUsername()

public function oneByUsername(string $username, bool $cached = true): ?User

UserRepository::oneByEmail()

public function oneByEmail(?string $email): ?User

UserRepository::byIds()

public function byIds(array $ids): array

UserRepository::activeWithin()

public function activeWithin(int $seconds, ?int $exceptId = null): array

UserRepository::oneById()

public function oneById(int $id): ?User

UserRepository::byRoles()

public function byRoles(array|string $roles): array

UserRepository::byUsernameContaining()

public function byUsernameContaining(string $term, int $limit = 50): array

UserRepository::findActiveAdmins()

public function findActiveAdmins(int $onlineDelay, ?int $excludeId = null): array

UserRepository::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): void

Atomic 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): int

PageViewRepository::earliestDate()

public function earliestDate(): ?\DateTimeImmutable

PageViewRepository::dailyBreakdown()

public function dailyBreakdown(\DateTimeImmutable $since, string|array|null $path = null): array

PageViewRepository::dailyBreakdownBySource()

public function dailyBreakdownBySource(\DateTimeImmutable $since, string|array|null $path = null): array

PageViewRepository::hourlyBreakdown()

public function hourlyBreakdown(\DateTimeImmutable $since, string|array|null $path = null): array

PageViewRepository::hourlyBreakdownBySource()

public function hourlyBreakdownBySource(\DateTimeImmutable $since, string|array|null $path = null): array

PageVisitRepository 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): void

PageVisitRepository::countUnique()

public function countUnique(?\DateTimeImmutable $since = null, string|array|null $path = null): int

PageVisitRepository::dailyBreakdown()

public function dailyBreakdown(\DateTimeImmutable $since, string|array|null $path = null): array

PageVisitRepository::hourlyBreakdown()

public function hourlyBreakdown(\DateTimeImmutable $since, string|array|null $path = null): array

VisitRepository 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): void

VisitRepository::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): int

VisitRepository::returning()

public function returning(string $subjectType, \DateTimeImmutable $previousSince, \DateTimeImmutable $currentSince): array

VisitRepository::dailyBreakdown()

public function dailyBreakdown(string $subjectType, \DateTimeImmutable $since): array

VisitRepository::hourlyBreakdown()

public function hourlyBreakdown(string $subjectType, \DateTimeImmutable $since): array

Omnibridge\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): array

RevisionRepository::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): array

TrashBallRepository::countContents()

public function countContents(?string $entityClass = null): int

TrashBallRepository::expired()

public function expired(?\DateTimeInterface $now = null, ?int $limit = null): array

TrashBallRepository::forEntity()

public function forEntity(string $entityClass, int $entityId): ?TrashBall

Omnibridge\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): ?ScopedWeek

ScopedWeekRepository::week()

public function week(string $scope): ?array

ScopedWeekRepository::save()

public function save(string $scope, array $week): ScopedWeek

ScopedWeekRepository::forget()

public function forget(string $scope): void

SpecialDayRepository 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): array

WeekDayHoursRepository 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(): array

WeekDayHoursRepository::save()

public function save(array $week): void

Omnibridge\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): ?ImageCrop

ImageCropRepository::oneClosestToRatio()

public function oneClosestToRatio(float|int $ratio0, string $source): ?ImageCrop

ImageCropRepository::oneClosestToRatioAndSize()

public function oneClosestToRatioAndSize(float|int $ratio0, float|int $width0, float|int $height0, string $source): ?ImageCrop

RedirectionRepository 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): ?Redirection

RedirectionRepository::hit()

public function hit(Redirection $redirection): void

omnibridge/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(): array

SettingRepository 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): array

SettingRepository::oneByInsensitivePath()

public function oneByInsensitivePath(string $path): ?Setting

TextOverrideRepository 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): ?Widget

WidgetRepository::every()

public function every(bool $cached = true): array

Omnibridge\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): ?Slot

Omnibridge\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): array

CommentRepository::countVisible()

public function countVisible(?Thread $thread): int

CommentRepository::countPending()

public function countPending(): int

CommentRepository::findPending()

public function findPending(int $limit = 20): array

CommentRepository::findLastFromIp()

public function findLastFromIp(string $ip): ?Comment

LikeRepository 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): ?Like

MentionRepository 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): array

TagRepository 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): ?Tag

TagRepository::bySlugs()

public function bySlugs(array $slugs): array

TagRepository::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): array

ConnectionRepository 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): ?Connection

ConnectionRepository::countFor()

public function countFor(User $user): int

IdentityRepository 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): ?Identity

IdentityRepository::findOfUser()

public function findOfUser(object $user): array

NotificationRepository 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): int

NotificationRepository::findVisibleFor()

public function findVisibleFor(User $user, int $limit = 100, int $offset = 0, bool $unreadOnly = false): array

PasskeyRepository 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): ?Passkey

PasskeyRepository::findAllForUserEntity()

public function findAllForUserEntity(PublicKeyCredentialUserEntity $publicKeyCredentialUserEntity): array

PasskeyRepository::findOneByCredentialId()

public function findOneByCredentialId(string $publicKeyCredentialId): ?CredentialRecord

PasskeyRepository::saveCredentialRecord()

public function saveCredentialRecord(CredentialRecord $credentialRecord): void

PasskeyRepository::credentialRecord()

public static function credentialRecord(Passkey $passkey): CredentialRecord

PasskeyRepository::fill()

public static function fill(Passkey $passkey, CredentialRecord $record): Passkey

PushSubscriptionRepository 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(): int

TokenRepository 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): ?Token

TokenRepository::oneByValue()

public function oneByValue(?string $value): ?Token

TokenRepository::oneSigningInByNameAndValue()

public function oneSigningInByNameAndValue(string $name, ?string $value): ?Token

TokenRepository::oneSigningInByValue()

public function oneSigningInByValue(?string $value): ?Token