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

Myclabs Enum Param Converter Laravel Package

ex3v/myclabs-enum-param-converter

A Symfony bundle that adds seamless MyCLabs\Enum parameter conversion in controllers. Install via Composer, register the bundle, typehint enum arguments in actions, and conversion happens automatically.

View on GitHub
Deep Wiki
Context7

Getting Started

Before you composer require anything, note the framing: this is a Symfony bundle, not a Laravel package. If your assessment target is a Laravel codebase, the only thing you can actually reuse is the idea — a route parameter that hydrates into an enum object. In Laravel that's a three-line binding in RouteServiceProvider; in Symfony this bundle is the equivalent plumbing.

If you genuinely are on Symfony (2.x/3.x era, given the AppKernel instructions):

composer require ex3v/myclabs-enum-param-converter

You'll also need myclabs/php-enum and sensio/framework-extra-bundle — the README doesn't declare them as hard requirements but @ParamConverter comes from the latter, and the converter obviously needs the former. Expect to install both explicitly.

Then register the bundle. On legacy Symfony, in app/AppKernel.php:

new \Ex3v\MyCLabsEnumParamConverterBundle\MyCLabsEnumParamConverterBundle(),

On Symfony 4+, in config/bundles.php:

Ex3v\MyCLabsEnumParamConverterBundle\MyCLabsEnumParamConverterBundle::class => ['all' => true],

Where to look first: the source. The README is the entire documentation, and the bundle is small — open vendor/ex3v/myclabs-enum-param-converter/ and read the converter class (plus its services.xml) before writing a single controller. Two questions to answer there, because the README doesn't:

  1. Does it construct with new $class($value) (matching on the enum value) or with $class::$name() (matching on the constant name)? This determines what your route segment must contain.
  2. What exception does it throw on an unknown value — and does the framework turn that into a 404/400 or a 500?

First use case: a status/type filter in a URL where you want the controller to receive a typed object rather than a raw string:

/**
 * @ParamConverter("barType")
 */
public function fooAction(BarType $barType): Response
{
    // $barType instanceof BarType, no manual new BarType($request->get('barType'))
}

That's the whole value proposition: you delete a defensive new BarType(...) from every action and get a 404-or-400 instead of a UnexpectedValueException bubbling up from the enum constructor.

Implementation Patterns

Rely on the typehint, not the annotation name. The bundle's selling point (per the README) is that the converter's supports() inspects the controller argument's type, so @ParamConverter("barType") alone is enough. Use the shorthand as the default:

/**
 * @ParamConverter("barType")
 */
public function listAction(BarType $barType): Response

Switch to the explicit converter name when ambiguity is possible.

/**
 * @ParamConverter("barType", converter="converter_enum")
 */

This matters in real apps because DoctrineParamConverter also claims route parameters that look like entities, and converter priority/order is not something you want to reason about. Naming the converter makes routing deterministic and saves you a debugging session six months later. Also note the argument name in the annotation and the parameter name must match, and the parameter must be type-hinted — the converter is driven off reflection.

Design your routes around the enum, not the other way round. The route placeholder is the input to the enum constructor, so:

// config/routes.yaml
foo:
    path: /foo/{barType}
    defaults: { barType: active }   // if the enum supports a default

Keep the segment alphabet narrow (constant-name- or value-shaped), and if the enum has multi-word or oddly-cased values, confirm the URL encoding round-trip by hitting it once. This is the kind of thing worth a single integration test rather than a convention.

Push the enum straight into the service layer. Once the controller argument is a BarType, services should accept BarType (or MyCLabs\Enum\Enum) and never re-validate:

public function fooAction(BarType $barType, ReportService $reports): Response
{
    return $this->render('foo.html.twig', [
        'report' => $reports->forType($barType),
    ]);
}

Keep the enum as the single source of truth for choices. For form dropdowns, feed BarType::toArray() into a ChoiceType; for API payloads, serialise back with ->getValue(). The converter only handles the inbound route case — do not assume it also handles JSON bodies or query strings.

Laravel equivalent (for cross-team comparison). If you're evaluating this as a pattern rather than adopting the bundle:

// RouteServiceProvider::boot()
Route::bind('barType', fn (string $value) => BarType::from($value));

BackedEnum::from() throws ValueError on unknown input — wrap it in try/catch and abort(404) to reproduce the converter's behaviour.

Gotchas and Tips

This package is effectively superseded — twice over. myclabs/php-enum itself tells you to migrate to native PHP 8.1 enums, and Symfony ≥6.2 ships BackedEnumValueResolver, which maps a route parameter directly to a backed enum via typehint with no bundle at all. So the honest day-to-day assessment: on anything modern, write

public function foo(BarType $barType) // BarType: BackedEnum

and skip the dependency. Adopt this bundle only if you're pinned to an old Symfony and an old MyCLabs\Enum and the migration isn't on the table.

It's a low-traffic, unaudited dependency. 8 stars, 0 dependents, readme-level maturity, Travis CI badge. Nothing about that is disqualifying for a ~100-line adapter, but it does mean: read the source, and be prepared to fork or vendor the converter yourself. A single custom ParamConverter implementing supports()/apply() is genuinely a short class — often shorter than the process of justifying the dependency.

Value-vs-name mismatch is the #1 failure mode. If the converter does new $class($raw), then /foo/ACTIVE fails while /foo/active works, and the resulting exception may look like a routing bug. Verify against one enum constant before wiring up ten routes. MyCLabs\Enum also throws UnexpectedValueException (not a Symfony HTTP exception) — if the converter doesn't wrap it, you get a 500 on bad input rather than a 404. Check this explicitly; it's a security-relevant difference (500s leak stack traces in dev, log noise in prod).

Nullable / optional parameters aren't described. If the route parameter is optional, the converter may still be invoked with null and blow up in the enum constructor. Prefer route defaults that map to a real enum constant over trying to make the argument nullable.

Debugging checklist when the converter "isn't firing":

  • bin/console debug:router foo — confirm the placeholder name matches the annotation.
  • Confirm the sensio/framework-extra-bundle listener is enabled (debug:event-dispatcher on older versions).
  • Dump $request->attributes->all() at the top of the action — if the raw string is still there and the argument is unhydrated, supports() returned false; that's almost always a missing/mismatched typehint or a wrong FQCN in the use statement.
  • Temporarily set the explicit converter="converter_enum" to rule out the Doctrine converter winning the race.

Extension points are thin but present. The converter is a normal service — you can override its definition, decorate it, or register your own converter with the same tag if you need behaviour the bundle doesn't offer (e.g. mapping 404 instead of 500, case-insensitive matching, or accepting both value and constant name). Look at the bundle's Resources/config/services.xml for the tag name and service id before you write anything.

Don't let it creep past the controller boundary. The bundle solves exactly one problem: HTTP string → enum at the edge. If you find yourself needing enum conversion in console commands, message handlers, or form data mappers, you want a shared Enum::fromString() helper, not more of 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.
abbasudo/artisan-route
mirvan/ippanel
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