77use Swoft \Bean \Annotation \Bean ;
88use Swoft \Core \RequestContext ;
99use Swoft \Exception \InvalidArgumentException ;
10+ use Swoft \Helper \JsonHelper ;
1011use Swoft \Helper \PhpHelper ;
12+ use Swoft \Helper \StringHelper ;
1113use Swoft \Http \Message \Router \HandlerAdapterInterface ;
1214use Swoft \Http \Message \Server \Request ;
1315use Swoft \Http \Message \Server \Response ;
1719use Swoft \Http \Server \Payload ;
1820
1921/**
20- * http handler adapter
21- *
2222 * @Bean("httpHandlerAdapter")
23- * @author stelin <[email protected] > 2423 */
2524class HandlerAdapter implements HandlerAdapterInterface
2625{
2726 /**
28- * execute handler with controller and action
27+ * Execute handler with controller and action
28+ *
2929 * @param ServerRequestInterface $request request object
3030 * @param array $routeInfo handler info
3131 * @return Response
@@ -89,11 +89,10 @@ public function doHandler(ServerRequestInterface $request, array $routeInfo)
8989 }
9090
9191 /**
92- * create handler
92+ * Create handler
9393 *
9494 * @param string $path url path
9595 * @param array $info path info
96- *
9796 * @return array
9897 * @throws \InvalidArgumentException
9998 */
@@ -142,10 +141,7 @@ public function createHandler(string $path, array $info): array
142141 }
143142
144143 /**
145- * default handler
146- *
147144 * @param array $handler handler info
148- *
149145 * @return array
150146 * @throws \Swoft\Exception\InvalidArgumentException
151147 */
@@ -163,12 +159,11 @@ private function defaultHandler(array $handler): array
163159 }
164160
165161 /**
166- * binding params of action method
162+ * Binding params of action method
167163 *
168164 * @param ServerRequestInterface $request request object
169165 * @param mixed $handler handler
170166 * @param array $matches route params info
171- *
172167 * @return array
173168 * @throws \ReflectionException
174169 */
@@ -184,10 +179,8 @@ private function bindParams(ServerRequestInterface $request, $handler, array $ma
184179 }
185180
186181 $ bindParams = [];
187- // $matches = $info['matches'] ?? [];
188- $ response = RequestContext::getResponse ();
189182
190- // binding params
183+ // Binding params
191184 foreach ($ reflectParams as $ key => $ reflectParam ) {
192185 $ reflectType = $ reflectParam ->getType ();
193186 $ name = $ reflectParam ->getName ();
@@ -203,16 +196,25 @@ private function bindParams(ServerRequestInterface $request, $handler, array $ma
203196 }
204197
205198 /**
206- * defined type of the param
199+ * Defined type of the param
207200 * @notice \ReflectType::getName() is not supported in PHP 7.0, that is why use __toString()
208201 */
209202 $ type = $ reflectType ->__toString ();
210203 if ($ type === Request::class) {
204+ // Current Request Object
211205 $ bindParams [$ key ] = $ request ;
212206 } elseif ($ type === Response::class) {
213- $ bindParams [$ key ] = $ response ;
207+ // Current Response Object
208+ $ bindParams [$ key ] = RequestContext::getResponse ();
214209 } elseif (isset ($ matches [$ name ])) {
210+ // Request parameters
215211 $ bindParams [$ key ] = $ this ->parserParamType ($ type , $ matches [$ name ]);
212+ } elseif (App::hasBean ($ type )) {
213+ // Bean
214+ $ bindParams [$ key ] = App::getBean ($ type );
215+ } elseif (\class_exists ($ type )) {
216+ // Class
217+ $ bindParams [$ key ] = $ this ->bindRequestParamsToClass ($ request , new \ReflectionClass ($ type ));
216218 } else {
217219 $ bindParams [$ key ] = $ this ->getDefaultValue ($ type );
218220 }
@@ -221,6 +223,44 @@ private function bindParams(ServerRequestInterface $request, $handler, array $ma
221223 return $ bindParams ;
222224 }
223225
226+ /**
227+ * Bind request parameters to instance of ReflectClass
228+ *
229+ * @param ServerRequestInterface $request
230+ * @param \ReflectionClass $reflectClass
231+ * @return Object
232+ */
233+ private function bindRequestParamsToClass (ServerRequestInterface $ request , \ReflectionClass $ reflectClass )
234+ {
235+ try {
236+ $ object = $ reflectClass ->newInstance ();
237+ $ queryParams = $ request ->getQueryParams ();
238+ // Get request body, auto decode when content type is json format
239+ if (StringHelper::startsWith ($ request ->getHeaderLine ('Content-Type ' ), 'application/json ' )) {
240+ $ requestBody = JsonHelper::decode ($ request ->getBody ()->getContents (), true );
241+ } else {
242+ $ requestBody = $ request ->getParsedBody ();
243+ }
244+ // Merge query params and request body
245+ $ requestParams = array_merge ($ queryParams , $ requestBody );
246+ // Binding request params to target object
247+ $ properties = $ reflectClass ->getProperties ();
248+ foreach ($ properties as $ property ) {
249+ $ name = $ property ->getName ();
250+ if (!isset ($ requestParams [$ name ])) {
251+ continue ;
252+ }
253+ if (!$ property ->isPublic ()) {
254+ $ property ->setAccessible (true );
255+ }
256+ $ property ->setValue ($ object , $ requestParams [$ name ]);
257+ }
258+ } catch (\Exception $ e ) {
259+ $ object = null ;
260+ }
261+ return $ object ;
262+ }
263+
224264 /**
225265 * parser the type of binding param
226266 *
0 commit comments