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

Api Doc Laravel Package

pedrotroller/api-doc

Pedrotroller/api-doc helps Laravel developers generate and serve API documentation directly from their application, turning routes and annotations into browsable reference docs that stay in sync with the code. Lightweight and easy to integrate.

View on GitHub
Deep Wiki
Context7

Getting Started

First, verify the package is still viable for your stack. This package was last released in 2016, targets the NelmioApiDocBundle 2.x era (Symfony 2.7–3.x, PHP 5.5–7.x), and has effectively zero downstream users. If you're on Symfony 4+ or NelmioApiDocBundle 3.x/4.x, stop here and read the Gotchas section — the extension points it relies on no longer exist.

If you're maintaining a legacy application that already matches that stack:

  1. Read the source before installing. With a single star and no external documentation beyond the README, src/ is the documentation. Start with the bundle class and DependencyInjection/ to see what it registers, then the annotation/handler classes to understand how translation is injected.
  2. Install:
    composer require pedrotroller/api-doc
    
    Pin the exact constraint from the last tag (1.0.x or dev-master) — there will be no patch releases.
  3. Register the bundle in app/AppKernel.php alongside Nelmio:
    new Nelmio\ApiDocBundle\NelmioApiDocBundle(),
    new PedroTroller\ApiDocBundle\PedroTrollerApiDocBundle(),
    
    Confirm the actual bundle FQCN and alias (pedro_troller_api_doc by convention) from composer.json autoload and the bundle class name.
  4. Dump the container to prove wiring is intact:
    php app/console debug:container | grep -i apidoc
    
    You're looking for a decorator or tagged handler wrapping nelmio_api_doc.extractor.
  5. First use case: annotate one controller action with @ApiDoc and replace a hard-coded description with a translation key, then request /api/doc in two locales (?locale=fr, ?locale=en) and confirm the rendered HTML differs. That single smoke test tells you whether the translator is actually being invoked or you're just seeing the raw key.

Implementation Patterns

Decorate, don't fork. The package's whole value is intercepting Nelmio's extraction pipeline so that @ApiDoc strings pass through Symfony's translator before reaching the formatter. In practice this means:

  • A tagged handler registered on nelmio_api_doc.extractor.handler (the v2 extension point) whose supports() returns true and whose handle() mutates the ApiDoc object — translating description, documentation, input, output, statusCodes, and requirement descriptions.
  • Or, more likely given the name, custom annotations that mark a doc field as translatable, e.g. a @Trans / @Translate annotation next to @ApiDoc, with the handler resolving $annotation->getMessage() through TranslatorInterface::trans() using the current request locale.

Recommended workflow for a multi-locale API:

  1. Separate content from structure. Keep route, method, and status codes in the controller annotation; move all human-readable prose into app/Resources/translations/apidoc.<locale>.yml, keyed by controller/action:
    # apidoc.en.yml
    api.user.list.description: "Returns a paginated list of users."
    api.user.list.param.page: "Page number, 1-indexed."
    
  2. Drive locale from the request, not from config. Symfony's translator already picks up _locale from the firewall or the query string; the extension should read $request->getLocale(). Verify this — a common shortcut in small bundles is to read %locale% from parameters, which breaks per-request switching.
  3. Cache the rendered docs per locale. Nelmio's HTML formatter is cheap, but a translator round-trip per field across hundreds of endpoints adds up. Cache nelmio_api_doc.controller.swagger / the HTML dump at the HTTP level with Vary: Accept-Language.
  4. Test the translation boundary, not the bundle. A single functional test that asserts a known key resolves to a known string for en and fr is enough coverage:
    $client->request('GET', '/api/doc', [], [], ['HTTP_ACCEPT_LANGUAGE' => 'fr']);
    $this->assertContains('Liste paginée', $client->getResponse()->getContent());
    
  5. Fallback explicitly. Register the bundle's translator domain (likely apidoc or messages) in config.yml with fallback: en so an untranslated endpoint degrades to English rather than showing a raw message id in production docs.

Integration tip: if the package's annotation handler proves brittle, the same result is achievable with a thin custom handler of your own — roughly 40 lines implementing HandlerInterface, translating $annotation->getDescription() in handle(). For a package this small and this unmaintained, reimplementing the useful 10% is often the lower-risk path.

Gotchas and Tips

  • It is abandoned in all but name. Last release June 2016, one star, zero dependents. No security policy, no issue triage, no compatibility updates. Treat any composer update as capable of breaking it silently, and pin with composer.lock committed.
  • Version incompatibility is the headline risk. NelmioApiDocBundle 3.x replaced the extractor/handler system with parsers and Document objects; 4.x removed annotations entirely in favor of PHP attributes. This package targets the 2.x @ApiDoc annotation world. There is no upgrade path. On a modern stack the equivalent is #[Model] / #[OA\...] attributes plus an injected TranslatorInterface in the controller, or translating inside a custom DescribableInterface implementation.
  • Doctrine annotations are deprecated. Even on a legacy stack, doctrine/annotations is on a removal path (PHP 8 attributes are the replacement in Symfony 6.4+/7). A 2016 annotation-based extension compounds that debt.
  • Container debugging is your first tool. If docs render untranslated, debug:container --tag=nelmio_api_doc.extractor.handler and debug:event-dispatcher reveal whether the service registered at all. Silent no-ops (service not tagged, tag name typo'd for your Nelmio version) are the most common failure mode — you get English text, not an error.
  • Watch the translator domain and catalogue loading. Small bundles frequently hardcode a domain that isn't registered in framework.translator, so trans() returns the key. Symptom: docs show api.user.list.description verbatim. Fix by registering the bundle's Resources/translations path — Symfony auto-registers bundle translations only if the files follow the Resources/translations/<domain>.<locale>.<format> convention exactly.
  • Locale leakage across cached responses. Without Vary: Accept-Language (or locale in the URL), a proxy or Symfony's HTTP cache will serve the French doc to an English client. This is the bug that bites after go-live, not during development.
  • Extension points if you must patch it: the bundle is small enough to composer patch or vendor-fork in a day. Prefer forking into your own src/ under an internal namespace over patching vendor/ — you keep the behaviour, drop the dependency, and gain the ability to modernize the annotation reader.
  • Don't advertise it internally as a dependency. With one star and a 2016 release, the honest recommendation for anything greenfield is: skip this package, put your API prose in translation catalogues, and resolve keys with the translator in a DescribableInterface or a small custom documentation handler. You'll write less code than you'll spend debugging this.
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.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core