1515use Hypervel \Router \Contracts \UrlRoutable ;
1616use Hypervel \Router \Exceptions \BackedEnumCaseNotFoundException ;
1717use Hypervel \Router \Exceptions \UrlRoutableNotFoundException ;
18+ use Hypervel \Router \Router ;
1819use Psr \Container \ContainerInterface ;
1920use Psr \Http \Message \ResponseInterface ;
2021use Psr \Http \Message \ServerRequestInterface ;
2526
2627class SubstituteBindings implements MiddlewareInterface
2728{
28- public function __construct (protected ContainerInterface $ container )
29- {
29+ /**
30+ * All of the resolved definitions by dispatched routes.
31+ */
32+ protected array $ resolvedDefinitions = [];
33+
34+ public function __construct (
35+ protected ContainerInterface $ container ,
36+ protected Router $ router
37+ ) {
3038 }
3139
3240 public function process (ServerRequestInterface $ request , RequestHandlerInterface $ handler ): ResponseInterface
@@ -38,13 +46,11 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
3846 return $ handler ->handle ($ request );
3947 }
4048
41- if (strpos ( $ dispatched -> handler -> route , ' { ' ) === false ) {
49+ if (! $ params = $ dispatched -> params ) {
4250 return $ handler ->handle ($ request );
4351 }
4452
4553 $ definitions = $ this ->getDefinitions ($ dispatched ->handler ->callback );
46- $ params = $ dispatched ->params ;
47-
4854 $ dispatched ->params = $ this ->substituteBindings ($ definitions , $ params );
4955
5056 return $ handler ->handle ($ request );
@@ -71,11 +77,14 @@ protected function getDefinitions(array|Closure|string $callback): array
7177 */
7278 protected function getClosureDefinitions (Closure $ callback ): array
7379 {
74- if (! $ this ->container ->has (ClosureDefinitionCollectorInterface::class)) {
75- return [];
80+ $ signature = spl_object_hash ($ callback );
81+ if ($ definitions = $ this ->resolvedDefinitions [$ signature ] ?? null ) {
82+ return $ definitions ;
7683 }
7784
78- return $ this ->container ->get (ClosureDefinitionCollectorInterface::class)->getParameters ($ callback );
85+ return $ this ->resolvedDefinitions [$ signature ] = $ this ->container ->has (ClosureDefinitionCollectorInterface::class)
86+ ? $ this ->container ->get (ClosureDefinitionCollectorInterface::class)->getParameters ($ callback )
87+ : [];
7988 }
8089
8190 /**
@@ -86,7 +95,12 @@ protected function getMethodDefinitions(array $callback): array
8695 $ controller = $ callback [0 ];
8796 $ action = $ callback [1 ];
8897
89- return $ this ->container ->get (MethodDefinitionCollectorInterface::class)->getParameters ($ controller , $ action );
98+ $ signature = "{$ controller }:: {$ action }" ;
99+ if ($ definitions = $ this ->resolvedDefinitions [$ signature ] ?? null ) {
100+ return $ definitions ;
101+ }
102+
103+ return $ this ->resolvedDefinitions [$ signature ] = $ this ->container ->get (MethodDefinitionCollectorInterface::class)->getParameters ($ controller , $ action );
90104 }
91105
92106 /**
@@ -100,7 +114,10 @@ protected function substituteBindings(array $definitions, array $params): array
100114 if (! array_key_exists ($ name , $ params )) {
101115 continue ;
102116 }
103-
117+ if ($ binding = $ this ->router ->getExplicitBinding ($ name )) {
118+ $ params [$ name ] = $ binding ($ params [$ name ]);
119+ continue ;
120+ }
104121 if ($ binding = $ this ->resolveBinding ($ definition , $ params , $ name )) {
105122 $ params [$ name ] = $ binding ;
106123 }
@@ -113,7 +130,7 @@ protected function substituteBindings(array $definitions, array $params): array
113130 * @throws ModelNotFoundException
114131 * @throws BackedEnumCaseNotFoundException
115132 */
116- protected function resolveBinding (ReflectionType $ definition , array $ params , string $ name )
133+ protected function resolveBinding (ReflectionType $ definition , array $ params , string $ name ): mixed
117134 {
118135 $ class = $ definition ->getName ();
119136
@@ -122,12 +139,17 @@ protected function resolveBinding(ReflectionType $definition, array $params, str
122139 }
123140
124141 if (is_a ($ class , Model::class, true )) {
125- return $ this ->resolveModel ($ class , $ params [$ name ]);
142+ return $ this ->resolveModel (
143+ $ this ->router ->getModelBinding ($ name ) ?: $ class ,
144+ $ params [$ name ]
145+ );
126146 }
127147
128148 if (is_a ($ class , BackedEnum::class, true )) {
129149 return $ this ->resolveBackedEnum ($ class , $ params [$ name ]);
130150 }
151+
152+ return null ;
131153 }
132154
133155 /**
0 commit comments