Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Beskedfordeler Symfony Laravel Package

itk-dev/beskedfordeler-symfony

A Symfony integration from itk-dev for Denmark's Beskedfordeler message distribution service, giving applications the plumbing needed to receive, route and handle messages delivered through the shared public-sector messaging infrastructure.

View on GitHub
Deep Wiki
Context7

Getting Started

First, establish what you actually have. The name and the sibling package situation matter here: ITK ships itk-dev/beskedfordeler-bundle (the reusable Symfony bundle for KOMBIT's Beskedfordeler) and this repository, beskedfordeler-symfony, which reads like the reference/demo Symfony application that wires that bundle into a running app. Before writing a line of code, open the repo and check three things in this order:

  1. composer.json — is the package type symfony-bundle, project, or library? Does it appear on Packagist, or do you need a repositories: [{type: vcs, url: ...}] entry?
  2. README.md and docs/ — ITK writes good Danish READMEs; the setup section is the real getting-started guide.
  3. src/ — look for a DependencyInjection/ folder (bundle) versus Kernel.php / config/ (app). This determines everything downstream.

Install and wire up. As of the 1.0.1 tag the package is at a stable 1.0.x line, so you can constrain to ^1.0 rather than pinning a branch alias:

composer require itk-dev/beskedfordeler-symfony:^1.0

If it is a bundle, register it and configure the connection to the Beskedfordeler queue (typically a separate database/DBAL connection, or an AMQP transport):

// config/bundles.php
ItkDev\BeskedfordelerBundle\BeskedfordelerBundle::class => ['all' => true],
# config/packages/beskedfordeler.yaml
beskedfordeler:
    database:
        url: '%env(BESKEDFORDELER_DATABASE_URL)%'

Then run whatever schema/seed command ships with it (ITK packages in this family usually expose beskedfordeler:create-database / beskedfordeler:cleanup-database style commands — check php bin/console list beskedfordeler).

Your first use case should be a no-op consumer. Don't start with real Digital Post routing. Write a single handler that receives a message, logs the beskedType, message UUID, and payload, and acknowledges it. That proves the whole chain — connection, polling/consumption, dispatch, ack — before you add business logic. Once you can see a message in var/log/dev.log, you have a working integration.

Where to look first when something is unclear: the KOMBIT Beskedfordeler spec is the ground truth for message formats and queue semantics. The package is a thin adapter over it; when a field or a lifecycle rule surprises you, the answer is almost always in the KOMBIT documentation, not the PHP.

Implementation Patterns

Handler-per-message-type (the "modtager" pattern). Beskedfordeler distributes heterogeneous messages — one handler per beskedType/beskedfordelerId keeps things sane. In a Symfony bundle context this is normally a tagged service interface:

final class BorgerMessageHandler implements BeskedfordelerMessageHandlerInterface
{
    public function supports(string $beskedType): bool
    {
        return $beskedType === 'borger-foo';
    }

    public function handle(BeskedfordelerMessage $message): void
    {
        // map payload, persist, dispatch domain event
    }
}

with tag autoconfiguration (beskedfordeler.message_handler) collecting them into a registry/chain. Confirm the exact interface and tag name in the bundle's services.xml — don't guess.

Symfony Messenger as the transport layer. If the package bridges into Messenger, prefer consuming via Messenger rather than hand-rolling a cron poller. A worker (bin/console messenger:consume beskedfordeler -vv) gives you retries, failure transport, and --limit/--time-limit for supervised restarts. Run it under systemd or Supervisor with --memory-limit — long-lived workers leak.

Idempotency is mandatory. Beskedfordeler is at-least-once in practice. Every handler should key on the message UUID: check-then-insert into a processed-messages table inside the same transaction as your business write. Retries and duplicate deliveries are normal, not exceptional.

Delete-after-ack, never before. The classic lifecycle is fetch → handle → delete/acknowledge. Wrap handling and deletion so a handler exception leaves the message in the queue for retry. If you delete first and crash, you silently lose a citizen's message.

Local development without the real queue. Seed your dev/test database with fixture rows shaped like real Beskedfordeler payloads (capture a few sanitized ones from a staging environment). Add a --dry-run flag or a beskedfordeler:fake-message command early; it pays for itself within a week. For integration tests, point the DBAL connection at SQLite or a Dockerized Postgres/MySQL and assert that a handler fires and the row is removed.

Layer the payload parsing. Parse the raw message into a typed DTO before it reaches business logic. The raw formats (XML or JSON depending on the queue generation) are verbose and full of optional fields; handlers should never touch SimpleXMLElement.

Gotchas and Tips

Maturity is the headline risk. Zero stars, zero dependents, first public release 2023-03-23, and the current tag is 1.0.1 — a patch release published via PR #3 with no functional changelog beyond "Release 1.0.1". Read that as: the project is being kept alive, not actively developed. It is internal ITK tooling, not a community library — expect Danish-only docs, sparse tests, and no support channel beyond the ITK GitHub org. Budget time to read the source rather than the docs.

Treat 1.0.1 as "no news is the news". There is no documented behaviour change between 1.0.0 and 1.0.1, so nothing in your integration should break on upgrade — but equally, nothing you were waiting for has been fixed. Do the upgrade as a routine patch bump (composer update itk-dev/beskedfordeler-symfony), then re-run your own integration test against a seeded queue; the release note gives you no other signal to rely on. If you carry a fork with bumped constraints, rebase onto the 1.0.1 tag and keep your diff small.

Symfony version drift. The 1.0.x line traces back to a March 2023 release, sitting in the Symfony 5.4/6.x window. A patch bump does not move framework constraints. Check composer.json constraints before adding it to a Symfony 7 app; you will likely hit PHP and framework conflicts. Options: pin your app to Symfony 6.4 LTS, or fork and bump constraints (usually a small diff, but you own it thereafter).

Don't confuse the two repositories. beskedfordeler-symfony vs. beskedfordeler-bundle. If you need to embed Beskedfordeler in an existing app, the bundle is what you want; this repo is more useful as a worked example to copy patterns from than as a dependency. Check the bundle's own release history too — it may not have been tagged in step with this 1.0.1.

Transport credentials. Production Beskedfordeler access requires an OCES system certificate (mTLS) or equivalent Kombit gateway credentials, plus network access through the municipality's infrastructure. You cannot fully exercise the real path from a laptop — plan for a staging environment with real credentials early, because certificate provisioning is slow and bureaucratic.

Encoding and locale. Danish characters (æ ø å) appear throughout payloads. Set UTF-8 explicitly on the DBAL connection and verify the XML/JSON parser handles them; silently mangled names in case handling are an ugly class of bug. Also check the timestamp format — Beskedfordeler uses a specific date format, and mixing it with DateTimeImmutable::createFromFormat guesses produces off-by-timezone records.

Silent failures in the cleanup path. If the package ships a cleanup/archival command, verify it only touches processed rows. A misconfigured retention window that deletes unhandled messages is a data-loss incident, not a bug report.

Extension points to lean on. Rather than forking, look for: (a) an event dispatched on message receipt, which lets you add logging/metrics via a subscriber; (b) the handler registry tag, which lets you add types without touching package code; (c) the DBAL connection configuration, which lets you point at an AMQP or a custom table. If none of those exist, a decorated service in your app's config/services.yaml is a cleaner override than patching vendor code — and it survives patch upgrades like 1.0.1 for free.

Debugging checklist when "no messages arrive": (1) is the connection pointing at the right database/queue, (2) does a manual SELECT show unprocessed rows, (3) is your handler registered and does supports() actually return true for the type you expect, (4) is the worker running and did it die on an uncaught exception, (5) check the failure transport. Nine times out of ten it is a supports() mismatch or a dead worker.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox