1. Go to this page and download the library: Download tiny-blocks/outbox library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
tiny-blocks / outbox example snippets
declare(strict_types=1);
use TinyBlocks\BuildingBlocks\Event\IntegrationEventTranslators;
use TinyBlocks\Outbox\DoctrineOutboxRepository;
use TinyBlocks\Outbox\Serialization\PayloadSerializerReflection;
use TinyBlocks\Outbox\Serialization\PayloadSerializers;
$repository = new DoctrineOutboxRepository(
connection: $connection,
serializers: PayloadSerializers::createFrom(elements: [
new PayloadSerializerReflection()
]),
translators: IntegrationEventTranslators::createFrom(elements: [
new OrderPlacedTranslator()
])
);
declare(strict_types=1);
use TinyBlocks\BuildingBlocks\Event\DomainEvent;
use TinyBlocks\BuildingBlocks\Event\DomainEventBehavior;
# A domain event. Stays internal to the bounded context. A translator maps it to the public contract.
final readonly class OrderPlaced implements DomainEvent
{
use DomainEventBehavior;
public function __construct(public string $orderId)
{
}
}
# Both the aggregate state change and the outbox write happen inside the same transaction.
$connection->beginTransaction();
try {
$order = Order::place(orderId: 'order-123');
$orderRepository->save(order: $order);
$outboxRepository->push(records: $order->recordedEvents());
$connection->commit();
} catch (Throwable $exception) {
$connection->rollBack();
throw $exception;
}
declare(strict_types=1);
use TinyBlocks\BuildingBlocks\Event\IntegrationEvent;
use TinyBlocks\BuildingBlocks\Event\IntegrationEventBehavior;
use TinyBlocks\BuildingBlocks\Event\Revision;
# Integration event class names use ubiquitous-language terms, not a suffix like IntegrationEvent.
final readonly class OrderShipped implements IntegrationEvent
{
use IntegrationEventBehavior;
public function __construct(public string $orderId)
{
}
}
# Bump revision() only when the public payload schema changes.
final readonly class PaymentConfirmed implements IntegrationEvent
{
use IntegrationEventBehavior;
public function revision(): Revision
{
return Revision::of(value: 2);
}
}
declare(strict_types=1);
use TinyBlocks\BuildingBlocks\Event\EventRecord;
use TinyBlocks\BuildingBlocks\Event\IntegrationEvent;
use TinyBlocks\BuildingBlocks\Event\IntegrationEventTranslator;
final readonly class OrderPlacedTranslator implements IntegrationEventTranslator
{
public function supports(EventRecord $record): bool
{
return $record->event instanceof OrderPlaced;
}
public function translate(EventRecord $record): IntegrationEvent
{
return new OrderShipped(orderId: $record->event->orderId);
}
}
declare(strict_types=1);
use TinyBlocks\BuildingBlocks\Event\IntegrationEventTranslators;
use TinyBlocks\Outbox\DoctrineOutboxRepository;
use TinyBlocks\Outbox\Serialization\PayloadSerializerReflection;
use TinyBlocks\Outbox\Serialization\PayloadSerializers;
$repository = new DoctrineOutboxRepository(
connection: $connection,
serializers: PayloadSerializers::createFrom(elements: [
new PayloadSerializerReflection()
]),
translators: IntegrationEventTranslators::createFrom(elements: [
new OrderPlacedTranslator(),
new PaymentReceivedTranslator()
])
);
declare(strict_types=1);
use TinyBlocks\BuildingBlocks\Event\IntegrationEventTranslators;
use TinyBlocks\Outbox\DoctrineOutboxRepository;
use TinyBlocks\Outbox\Serialization\PayloadSerializerReflection;
use TinyBlocks\Outbox\Serialization\PayloadSerializers;
# InventoryReserved has no translator registered: its row carries the domain event itself,
# with event_type InventoryReserved and a payload reflecting its public properties.
$repository = new DoctrineOutboxRepository(
connection: $connection,
serializers: PayloadSerializers::createFrom(elements: [
new PayloadSerializerReflection()
]),
translators: IntegrationEventTranslators::createFrom(elements: [
new OrderPlacedTranslator()
])
);
declare(strict_types=1);
use TinyBlocks\BuildingBlocks\Event\IntegrationEventTranslators;
use TinyBlocks\Outbox\DoctrineOutboxRepository;
use TinyBlocks\Outbox\Schema\Columns;
use TinyBlocks\Outbox\Schema\IdentityColumnType;
use TinyBlocks\Outbox\Schema\TableLayout;
use TinyBlocks\Outbox\Serialization\PayloadSerializerReflection;
use TinyBlocks\Outbox\Serialization\PayloadSerializers;
$tableLayout = TableLayout::builder()
->withColumns(columns: Columns::builder()
->withId(name: 'id', type: IdentityColumnType::STRING)
->withEventType(name: 'kind')
->withAggregateId(name: 'aggregate_id', type: IdentityColumnType::STRING)
->withAggregateType(name: 'entity_class')
->withAggregateVersion(name: 'position')
->build())
->withTableName(tableName: 'my_outbox')
->build();
$repository = new DoctrineOutboxRepository(
connection: $connection,
serializers: PayloadSerializers::createFrom(elements: [new PayloadSerializerReflection()]),
translators: IntegrationEventTranslators::createFrom(elements: [new OrderPlacedTranslator()]),
tableLayout: $tableLayout
);
declare(strict_types=1);
use TinyBlocks\BuildingBlocks\Event\IntegrationEventRecord;
use TinyBlocks\BuildingBlocks\Event\IntegrationEventTranslators;
use TinyBlocks\Outbox\DoctrineOutboxRepository;
use TinyBlocks\Outbox\Serialization\PayloadSerializer;
use TinyBlocks\Outbox\Serialization\PayloadSerializerReflection;
use TinyBlocks\Outbox\Serialization\PayloadSerializers;
use TinyBlocks\Outbox\Serialization\SerializedPayload;
final readonly class OrderEventSerializer implements PayloadSerializer
{
public function supports(IntegrationEventRecord $record): bool
{
return $record->event instanceof OrderShipped || $record->event instanceof OrderCanceled;
}
public function serialize(IntegrationEventRecord $record): SerializedPayload
{
return match (true) {
$record->event instanceof OrderShipped => SerializedPayload::from(
payload: json_encode(['orderId' => $record->event->orderId], JSON_THROW_ON_ERROR)
),
$record->event instanceof OrderCanceled => SerializedPayload::from(
payload: json_encode(
['orderId' => $record->event->orderId, 'reason' => $record->event->reason],
JSON_THROW_ON_ERROR
)
)
};
}
}
# Register custom serializers before PayloadSerializerReflection.
# PayloadSerializerReflection always returns true from supports(), so it must come last.
$repository = new DoctrineOutboxRepository(
connection: $connection,
serializers: PayloadSerializers::createFrom(elements: [
new OrderEventSerializer(),
new PayloadSerializerReflection()
]),
translators: IntegrationEventTranslators::createFrom(elements: [
new OrderPlacedTranslator(),
new OrderCanceledTranslator()
])
);
declare(strict_types=1);
use TinyBlocks\BuildingBlocks\Event\IntegrationEvent;
use TinyBlocks\BuildingBlocks\Event\IntegrationEventBehavior;
use TinyBlocks\BuildingBlocks\Event\Revision;
# Revision 2: a currency field was added to the public contract. Override revision() to declare the schema bump.
final readonly class OrderShipped implements IntegrationEvent
{
use IntegrationEventBehavior;
public function __construct(public string $orderId, public string $currency)
{
}
public function revision(): Revision
{
return Revision::of(value: 2);
}
}
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.