shopware / dynamodb-dal-bundle
A data abstraction layer for DynamoDB
Package info
github.com/shopware/dynamodb-dal-bundle
Type:symfony-bundle
pkg:composer/shopware/dynamodb-dal-bundle
Requires
- php: >=8.4
- async-aws/dynamo-db: ^3.11
- symfony/config: ^7.3 || ^8.0
- symfony/console: ^7.3 || ^8.0
- symfony/dependency-injection: ^7.3 || ^8.0
- symfony/http-foundation: ^7.3 || ^8.0
- symfony/http-kernel: ^7.3 || ^8.0
- symfony/service-contracts: ^3.5
Requires (Dev)
- async-aws/async-aws-bundle: ^1.17
- friendsofphp/php-cs-fixer: ^3.95.2
- phpstan/extension-installer: ^1.4.3
- phpstan/phpstan: ^2.1.55
- phpstan/phpstan-phpunit: ^2.0.16
- phpstan/phpstan-strict-rules: ^2.0.11
- phpstan/phpstan-symfony: ^2.0.18
- phpunit/phpunit: ^13.2.2
- symfony/clock: ^7.3 || ^8.0
- symfony/framework-bundle: ^7.3 || ^8.0
- symfony/http-client: ^7.3 || ^8.0
- symfony/stopwatch: ^7.3 || ^8.0
- symfony/uid: ^7.3 || ^8.0
- symfony/web-profiler-bundle: ^7.3 || ^8.0
- symfony/yaml: ^7.3 || ^8.0
Suggests
- async-aws/async-aws-bundle: Provides the AsyncAws DynamoDbClient service the DAL clients autowire
- symfony/framework-bundle: Needed for the profiler panel (DynamoDbDataCollector)
- symfony/uid: Enables Symfony Uid (Uuid/Ulid) entity properties
- symfony/web-profiler-bundle: Renders the DynamoDB profiler panel
Provides
None
Conflicts
None
Replaces
None
README
A data abstraction layer for DynamoDB, as a Symfony bundle.
Entities are plain PHP classes annotated with #[Table] and #[Field]. The bundle compiles them into definitions
when the container is built, then reads and writes them through AsyncAws. You work
with entities and PHP values; DynamoDB's attribute format stays inside the bundle.
- Typed fields: strings, numbers, booleans, dates, backed enums, Uids, lists and maps, and types of your own
- Get, query, scan and count, with one
Filterbuilder for key conditions, filters and write conditions - Puts, inserts, partial and nested updates, atomic counters and appends, and deletes, one at a time, in batches or in transactions, chunked and retried for you
- Opaque, URL-safe pagination tokens that page forward and backward
- Console commands that print a definition, check it against its live table and record a baseline for CI, and a profiler panel
Getting started
The quick setup covers the requirements, installation, a first entity and how to read and write it.
Documentation
- Quick setup: requirements, installation, a first entity and its use
- Basics: entities, reading by key, queries, scans, counts, filters, puts, inserts and deletes
- Updates, conditions and transactions: partial and nested updates, update expressions, upserts, conditional writes and transactions
- Paginated listing: previous and next links, page numbers, and pages merged from several queries
- Custom types, normalizers, filters and update actions
- Testing: doubles of the client, and tests of filters, update actions and normalizers of your own
- Exceptions: which exceptions to catch, and what each one means
- Limitations: what the entity model rules out, such as subclasses of an entity, and values that PHP and DynamoDB don't share, such as a float's precision and range
- Architecture decisions
Development tooling
In the dev environment, the bundle adds four console commands:
| Command | Output |
|---|---|
dal:definition:inspect [entity] |
The compiled definition of an entity: its table, keys and indexes, and every field's type, nullability, default, serializer and attribute type |
dal:definition:validate |
Compares every definition with its live table: the table and index keys, their attribute types, and whether each declared index exists and projects every field. Fails on any difference that makes requests fail, and warns of an index the definition does not declare |
dal:baseline:dump |
JSON with each entity's keys and indexes, and every field's attribute type and whether it is required. Commit it, so that a later change can be compared with it |
dal:baseline:compare <baseline> |
What changed since a baseline, and what each change risks once deployed: breaking, such as a field that turns required or is stored as another type, caution, such as a new index the table needs first, or safe. - reads the baseline from standard input, and --format=markdown prints it for a pull request |
Baseline in CI
The bundle's composite action compares a pull request with the baseline committed on its base branch. It keeps a comment on the pull request that lists every change, grouped by risk, and says why each one matters, and it removes the comment once nothing changes any more. On any event, it fails where the committed baseline is out of date, so the next pull request compares with what was merged:
jobs: dal-baseline: runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps: - uses: actions/checkout@v7 # Set up PHP and install the application's dependencies here - uses: ./vendor/shopware/dynamodb-dal-bundle/.github/actions/baseline with: baseline: dal-baseline.json console: php bin/console --env=dev
The action ships from 0.7.1 and needs no DynamoDB. For an application in app/, prefix the path with app/ and set
working-directory: app. action.yml lists the other inputs. Pull requests
from forks get the report in the job summary instead of a comment.
Profiler
With symfony/web-profiler-bundle installed, the profiler gets a DynamoDB panel. It lists each call a request made
into the DAL, with its caller, the time spent in it and the DynamoDB requests it sent. The time is the wall time
inside the DAL, AsyncAws and the network included. The panel reads the requests from Symfony's traced HTTP client,
so AsyncAws has to send them through a client named aws.base-client (default):
framework: http_client: scoped_clients: aws.base-client: scope: '.*' async_aws: http_client: aws.base-client
Setting async_aws.http_client turns off the retrying HTTP client that AsyncAws builds by default. To keep
retries, wrap aws.base-client with AsyncAws\Core\HttpClient\AwsHttpClientFactory::createRetryableClient().
Contributing
Read the guidelines before opening a pull request.
docker compose up -d # DynamoDB Local on port 8345; point DYNAMODB_ENDPOINT elsewhere to use another composer phpunit # the integration suite fails when no DynamoDB answers composer phpstan composer ecs