Skip to content

Symfony apps need manual edits before the bundle does anything #182

Closed

Description

@derpixler

Problem

After composer require zammad/zammad-api-client-php, nothing is wired up in a Symfony app. Three manual steps are needed:

  1. Register ZammadAPIClient\Bridge\SymfonyBundle in config/bundles.php.
  2. Create config/packages/zammad.yaml. The file is not optional: Symfony calls a bundle's extension only for an alias that has configuration, so without a zammad: section the bundle silently registers nothing, and a ZammadClient type-hint fails with a "non-existent service" error that does not point at the missing file.
  3. Add ZAMMAD_URL and ZAMMAD_TOKEN to .env.

Laravel users need none of this: the provider is auto-discovered via extra.laravel.providers. In discussion #174 this gap led to the suggestion of moving the bridges into separate packages.

Who is affected: every Symfony user of the bundle, and especially new ones. Step 2 is the easiest to miss and the hardest to diagnose.

Proposed change

Keep the bridges in this package. A separate repository would add a second release cycle without solving anything a recipe cannot. Instead, contribute a Flex recipe to symfony/recipes-contrib. Recipes are keyed by package name, so the library itself stays as it is.

zammad/zammad-api-client-php/3.2/manifest.json:

{
    "bundles": {
        "ZammadAPIClient\\Bridge\\SymfonyBundle": ["all"]
    },
    "copy-from-recipe": {
        "config/": "%CONFIG_DIR%/"
    },
    "env": {
        "ZAMMAD_URL": "https://zammad.example.com",
        "ZAMMAD_TOKEN": ""
    },
    "post-install-output": [
        "  * Set <fg=green>ZAMMAD_URL</> and <fg=green>ZAMMAD_TOKEN</> in <fg=green>.env.local</>"
    ]
}

zammad/zammad-api-client-php/3.2/config/packages/zammad.yaml:

zammad:
    url: '%env(ZAMMAD_URL)%'
    token: '%env(ZAMMAD_TOKEN)%'

Why 3.2: before 3.2.0 the bundle registered the client with ContainerBuilder::set() and failed in every compiled container (see the 3.2.0 changelog). A recipe for older versions would install a bundle that does not work.

Empty token: the recipe adds ZAMMAD_TOKEN= without a value. The container still compiles, because the client is a lazy definition. The first use of the client fails with "API token must not be empty." This matches the bundle's documented behaviour, and the post-install message points the user at it.

After the merge:

  • README, Symfony section: composer require becomes the setup. Manual registration remains documented as the fallback for apps without Flex or with contrib recipes disabled (Flex asks for confirmation before applying a contrib recipe unless extra.symfony.allow-contrib is set).
  • SymfonyBundle docblock: same change.
  • Reply in Symfony + Laravel Bridges #174.

Acceptance criteria

In a fresh symfony/skeleton (6.4, 7.4 and 8.1), a plain composer require zammad/zammad-api-client-php:

  • registers the bundle in config/bundles.php,
  • creates config/packages/zammad.yaml,
  • adds ZAMMAD_URL and ZAMMAD_TOKEN to .env,
  • with a token set, lets ZammadClient and zammad_client resolve from the container.

Also:

  • composer remove takes all three changes back out.
  • An app that already defines its own ZammadAPIClient\ZammadClient service (as shown in the custom HTTP client guide) keeps its definition. The bundle's definition must not override it.
  • Projects without Flex are unaffected.
  • The install job from composer require fails in a fresh Laravel 13 application #181 covers the Symfony path without manual registration.
  • The recipe is merged in symfony/recipes-contrib.

Out of scope

  • Separate bundle or provider packages (decided against, see above).
  • Symfony bundle configuration beyond url and token, such as ConnectionConfig options. That would be its own issue.

Verified

With the recipe served from a local Flex endpoint and the published 3.2.0, against fresh symfony/skeleton 6.4.50, 7.4.23 and 8.1.11: a plain composer require registers the bundle, creates config/packages/zammad.yaml, adds both variables to .env, and zammad_client resolves. An app-level ZammadAPIClient\ZammadClient definition in services.yaml takes precedence over the bundle's. composer remove reverts all three changes. A project without Flex gets neither config/ nor .env.

Update: ship the recipe ourselves, recipes-contrib second

Instead of depending on recipes-contrib alone, the recipe lives in this repository and is published with every release:

  • Source: src/Bridge/Symfony/recipe/3.2/ (same layout as recipes-contrib, excluded from the Composer dist via export-ignore).

  • Release artifact: a workflow builds a Flex endpoint (index.json plus one recipe file) from that source and attaches it to the GitHub release. Users add it once, before composer require:

    composer config --json extra.symfony.endpoint \
      '["https://github.com/zammad/zammad-api-client-php/releases/latest/download/index.json", "flex://defaults"]'

    The endpoint declares is_contrib: false, so no allow-contrib setting or prompt is needed.

  • Version 3.2: the recipe ships with the next patch release. Flex compares only major.minor of the client version, so a 3.2.1 folder would not apply before 3.3.0 (tested); 3.2 applies to 3.2.0 and later, where the bundle works.

  • CI: the install test from composer require fails in a fresh Laravel 13 application #181 applies the recipe through a local endpoint built from the same source, and checks that composer remove reverts it.

  • recipes-contrib: a PR from the same source can follow, so that the extra endpoint line becomes unnecessary for everyone.

Verified: GitHub's releases/latest/download/… chain (two redirects, host change to release-assets.githubusercontent.com, application/octet-stream) is followed by Composer's HttpDownloader. With that chain reproduced locally, Flex fetched both files through it and applied the recipe to a fresh Symfony 8.1 skeleton.

Activity

  1. self-assigned this
    on Nov 9, 2026
  2. derpixler commented on Nov 9, 2026

    @derpixler
    ContributorAuthor

    Shipped in v3.2.1 (#189): the release carries index.json and zammad.zammad-api-client-php.3.2.json. Verified against the real assets: fresh symfony/skeleton 6.4 and 8.1, only the documented extra.symfony.endpoint line, then composer require installs v3.2.1, applies the recipe, and zammad_client resolves. A PR to symfony/recipes-contrib from the same source remains optional.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions