Skip to content

Latest commit

 

History

History
115 lines (92 loc) · 7.31 KB

Sync.md

File metadata and controls

115 lines (92 loc) · 7.31 KB

Syncing data between backends

Sync providers

A sync provider is a class that implements SyncProviderInterface to propagate data to and from a backend, e.g. an API or database.

For a provider to perform sync operations on an entity of a given type, it must also implement the entity's provider interface, which--aside from entities with a registered namespace helper--has the following name:

<entity_namespace>\Provider\<entity>Provider

A provider servicing Acme\Sync\User entities would need to implement the Acme\Sync\Provider\UserProvider interface, for example.

Entity provider interfaces must extend SyncProviderInterface. They don't need to have declared methods, but sync operations can be implemented as declared methods if desired.

sli makes it easy to generate a provider interface for an entity:

vendor/bin/sli generate sync provider --magic --op 'get,get-list' 'Acme\Sync\User'

Namespace helpers

To map entity classes to different provider interfaces (or multiple entities to one interface, perhaps), you can provide a namespace helper to the entity store when registering a namespace. See registerNamespace() for details and SyncNamespaceHelper.php for a working example that maps Acme\Sync\Entity\User to Acme\Sync\Contract\ProvidesUser.

Operations

To perform a sync operation on an entity, a provider must implement its provider interface and either:

  1. return a closure for the operation and entity via getDefinition(), or
  2. declare a method for the operation using the naming convention below.

In either case, the signature for the implemented operation must be as follows. The first value passed is always the current context and optional arguments may be accepted after mandatory parameters.

Operation1 Closure signature Equivalent method2 Alternative method3
CREATE fn(SyncContextInterface $ctx, SyncEntityInterface $entity, ...$args): SyncEntityInterface create<EntitySingular> create_<Entity>
READ fn(SyncContextInterface $ctx, int|string|null $id, ...$args): SyncEntityInterface get<EntitySingular> get_<Entity>
UPDATE fn(SyncContextInterface $ctx, SyncEntityInterface $entity, ...$args): SyncEntityInterface update<EntitySingular> update_<Entity>
DELETE fn(SyncContextInterface $ctx, SyncEntityInterface $entity, ...$args): SyncEntityInterface delete<EntitySingular> delete_<Entity>
CREATE_LIST fn(SyncContextInterface $ctx, iterable $entities, ...$args): iterable create<EntityPlural> createList_<Entity>
READ_LIST4 fn(SyncContextInterface $ctx, ...$args): iterable get<EntityPlural> getList_<Entity>
UPDATE_LIST fn(SyncContextInterface $ctx, iterable $entities, ...$args): iterable update<EntityPlural> updateList_<Entity>
DELETE_LIST fn(SyncContextInterface $ctx, iterable $entities, ...$args): iterable delete<EntityPlural> deleteList_<Entity>

Contexts

Sync operations are performed within an immutable context created by the provider and replaced as needed to reflect changes to configuration and state. Contents include:

Description Getter(s) Setter(s) Notes
Provider getProvider() -
Service container getContainer() withContainer()
Entity type getEntityType() withEntityType()
Array key conformity getConformity() withConformity()
Entities getEntities(), getLastEntity() pushEntity() Tracks nested entity scope. See recursionDetected().
Parent entity getParent() withParent() Treeable entities only.
Arbitrary values hasValue(), getValue() withValue()
Operation hasOperation(), getOperation() withOperation() withOperation() also sets entity type.
Filters hasFilter(),getFilter(), getFilters() withOperation() Derived from non-mandatory arguments. See claimFilter().
Deferral policy getDeferralPolicy() withDeferralPolicy() Applies to nested entity retrieval.
Hydration policy getHydrationPolicy() withHydrationPolicy() Applies to entity relationship retrieval.
Offline mode getOffline() withOffline()

(Italicised entries are inherited from ProviderContextInterface.)

Footnotes

  1. See SyncOperation.

  2. Method names must match either the singular or plural form of the entity's unqualified name.

  3. Recommended when the singular and plural forms of a class name are the same. Method names must match the entity's unqualified name.

  4. See withOperation() for recognised signatures.