Skip to content

Commit

Permalink
camelCase route parameter so multi-word model binding works (#670)
Browse files Browse the repository at this point in the history
  • Loading branch information
Rasmus-Bertell authored Jun 30, 2023
1 parent 75fe8a5 commit ff59a30
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 4 deletions.
3 changes: 3 additions & 0 deletions src/Extracting/Shared/UrlParamsNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ protected static function getInlineRouteKey(Route $route, string $paramName): ?s
*/
protected static function getRouteKeyFromModel(string $paramName, array $typeHintedEloquentModels): ?string
{
// Ensure param name is in camelCase so it matches the argument name (e.g. The '$userAddress' in `function show(BigThing $userAddress`)
$paramName = Str::camel($paramName);

if (array_key_exists($paramName, $typeHintedEloquentModels)) {
$argumentInstance = $typeHintedEloquentModels[$paramName];
return $argumentInstance->getRouteKeyName();
Expand Down
5 changes: 5 additions & 0 deletions tests/Fixtures/TestController.php
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,11 @@ public function withInjectedModel(TestUser $user)
{
return null;
}

public function withInjectedModelFullParamName(TestPost $testPost)
{
return null;
}

public function withEnumRule(Request $request)
{
Expand Down
27 changes: 23 additions & 4 deletions tests/Unit/ExtractedEndpointDataTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Knuckles\Scribe\Scribe;
use Knuckles\Scribe\Tests\BaseLaravelTest;
use Knuckles\Scribe\Tests\Fixtures\TestController;
use Knuckles\Scribe\Tools\Utils as u;

class ExtractedEndpointDataTest extends BaseLaravelTest
{
Expand Down Expand Up @@ -99,24 +100,42 @@ public function normalizes_nonresource_url_params_with_inline_bindings()
$this->assertEquals('things/{thing}', $this->originalUri($route));
$this->assertEquals('things/{thing_slug}', $this->expectedUri($route));
}

/** @test */
public function normalizes_url_param_with_eloquent_model_binding()
{
Route::get("test-posts/{test_post}", [TestController::class, 'withInjectedModelFullParamName']);
$route = $this->getRoute(['prefixes' => '*']);

$this->assertEquals('test-posts/{test_post}', $this->originalUri($route));
$this->assertEquals('test-posts/{test_post_slug}', $this->expectedUri($route, withReflectedMethod: true));
}

protected function expectedUri(LaravelRoute $route): string
protected function expectedUri(LaravelRoute $route, $withReflectedMethod = false): string
{
return $this->endpoint($route)->uri;
return $this->endpoint($route, $withReflectedMethod)->uri;
}

protected function originalUri(LaravelRoute $route): string
{
return $route->uri;
}

protected function endpoint(LaravelRoute $route): ExtractedEndpointData
protected function endpoint(LaravelRoute $route, $withReflectedMethod = false): ExtractedEndpointData
{
if ($withReflectedMethod) {
[$controllerName, $methodName] = u::getRouteClassAndMethodNames($route);
$method = u::getReflectedRouteMethod([$controllerName, $methodName]);
} else {
// We're testing resource routes, and we may not have methods that exist for all of them (show, index, etc).
// Just use this dummy so we don't have null
$method = new \ReflectionFunction('dump');
}
return new ExtractedEndpointData([
'route' => $route,
'uri' => $route->uri,
'httpMethods' => $route->methods,
'method' => new \ReflectionFunction('dump'), // Just so we don't have null
'method' => $method,
]);
}

Expand Down

0 comments on commit ff59a30

Please sign in to comment.