You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Optional route params in urls such as /businesses/{businessCategory?} where BusinessCategory is an enum defined in the controller method as optional with a default of null (i.e. BusinessCategory $businessCategory = null) don't actually act as optional params as they should. They currently only support casting a default value to the route, e.g. BusinessCategory $businessCategory = BusinessCategory::MBA -- if you don't supply a default value and instead make this optional with = null, you do not get ANY route binding for the enum, which definitely doesn't seem to be intentional behaviour. It always resolves to null.
So what causes this? When ReflectionParameter->getType() is cast to string for an optional controller method param, it will return '?App\Enum\BusinessCategory', which cannot be infered as an enum via enum_exists() due to the preceeding '?' returned from the Reflection stringification, breaking this use case for a an actual optional enum route param.
To fix this, we can instead use ReflectionParameter->getType()?->getName() in a couple of places, and cast that to string instead, which will return the real enum in its namespace (or empty string if it was null, maintain existing behaviour).
I have a fix for this ready to go with updated tests for the ImplicitBackedEnumRouteBindingTest class
Steps To Reproduce:
Given an enum
<?php
namespace App\Enums;
enum BusinessCategory: string
{
case MBA = 'mba';
case CIA = 'cia';
}
<?php
namespace App\Http\Controllers;
use App\Enums\BusinessCategory;
class BusinessController extends Controller{
public function index(BusinessCategory $businessCategory = null): void
{
dd($businessCategory);
}
}
If you implement this normal optional routing pattern, where you would expect the nullable route param to resolve if supplied and to be null if not supplied, you instead get NO enum binding at all. $businessCategory is always null.
The text was updated successfully, but these errors were encountered:
Description:
Optional route params in urls such as
/businesses/{businessCategory?}
where BusinessCategory is an enum defined in the controller method as optional with a default of null (i.e.BusinessCategory $businessCategory = null
) don't actually act as optional params as they should. They currently only support casting a default value to the route, e.g.BusinessCategory $businessCategory = BusinessCategory::MBA
-- if you don't supply a default value and instead make this optional with= null
, you do not get ANY route binding for the enum, which definitely doesn't seem to be intentional behaviour. It always resolves to null.So what causes this? When
ReflectionParameter->getType()
is cast to string for an optional controller method param, it will return'?App\Enum\BusinessCategory'
, which cannot be infered as an enum via enum_exists() due to the preceeding '?' returned from the Reflection stringification, breaking this use case for a an actual optional enum route param.To fix this, we can instead use
ReflectionParameter->getType()?->getName()
in a couple of places, and cast that to string instead, which will return the real enum in its namespace (or empty string if it was null, maintain existing behaviour).I have a fix for this ready to go with updated tests for the
ImplicitBackedEnumRouteBindingTest
classSteps To Reproduce:
Given an enum
used as an optional route param
Route::get('/businesses/{businessCategory?}', [BusinessController::class, 'index']);
for a controller
If you implement this normal optional routing pattern, where you would expect the nullable route param to resolve if supplied and to be null if not supplied, you instead get NO enum binding at all. $businessCategory is always null.
The text was updated successfully, but these errors were encountered: