在Zend Framework 2应用程序的Module
类中,我向特殊端点发送HTTP请求以获取有关用户的一些信息。当我在工厂内执行此操作时(s。下面的代码中的第一种方法),它可以工作。它也适用于Module#onBootstrap(...)
(s。第二种方法)中的侦听器定义。但是当我尝试直接从Module#onBootstrap(...)
(s。 3d方法)执行调用时,调用失败并显示错误:
PHP Fatal error: Uncaught exception 'Zend\\Http\\Client\\Adapter\\Exception\\TimeoutException' with message 'Read timed out after 30 seconds' in /var/www/path/to/project/vendor/zendframework/zend-http/src/Client/Adapter/Socket.php:600
Stack trace:
#0 /var/www/path/to/project/vendor/zendframework/zend-http/src/Client/Adapter/Socket.php(412): Zend\\Http\\Client\\Adapter\\Socket->_checkSocketReadTimeout()
#1 /var/www/path/to/project/vendor/zendframework/zend-http/src/Client.php(1389): Zend\\Http\\Client\\Adapter\\Socket->read()
#2 /var/www/path/to/project/vendor/zendframework/zend-http/src/Client.php(893): Zend\\Http\\Client->doRequest(Object(Zend\\Uri\\Http), 'POST', false, Array, '')
#3 /var/www/path/to/project/module/MyApi/src/MyApi/Module.php(158): Zend\\Http\\Client->send()
#4 /var/www/path/to/project/module/MyApi/src/MyApi/Module.php(33): MyApi\\Module->retrieveUserInfosEndpoint(Object(ZF\\ContentNegotiation\\Request), 'http://my-project...')
#5 [intern in /var/www/path/to/project/vendor/zendframework/zend-http/src/Client/Adapter/Socket.php on line 600
为什么会出现错误?如何从Module#onBootstrap(...)发送HTTP请求?
namespace MyModule;
...
class Module
{
protected $userInfo;
public function onBootstrap(MvcEvent $mvcEvent)
{
// 3d approach -- it does NOT work
$userInfoEndpointUrl = $serviceManager->get('Config')['user_info_endpoint_url'];
$request = $serviceManager->get('Request');
$this->userInfo = $this->retrieveUserInfosEndpoint($request, $userInfoEndpointUrl);
...
$halPlugin->getEventManager()->attach('myeventname', function ($event) use (..., $serviceManager) {
// 2nd approach -- it works
$userInfoEndpointUrl = $serviceManager->get('Config')['user_info_endpoint_url'];
$request = $serviceManager->get('Request');
$this->userInfo = $this->retrieveUserInfosEndpoint($request, $userInfoEndpointUrl);
/*
PHP Fatal error:
Uncaught exception 'Zend\\Http\\Client\\Adapter\\Exception\\TimeoutException'
with message 'Read timed out after 30 seconds'
in /var/www/path/to/project/vendor/zendframework/zend-http/src/Client/Adapter/Socket.php:600
*/
...
});
...
}
...
public function getServiceConfig()
{
return array(
'factories' => array(
'MyModule\\V1\\Rest\\Foo\\FooService' => function(ServiceManager $serviceManager) {
// 1st approach -- it works
$userInfoEndpointUrl = $serviceManager->get('Config')['user_info_endpoint_url'];
$request = $serviceManager->get('Request');
$this->userInfo = $this->retrieveUserInfosEndpoint($request, $userInfoEndpointUrl);
...
return $fooService;
},
...
),
...
);
}
private function retrieveUserInfosEndpoint($request, $userInfoEndpointUrl)
{
$authorizationHeaderValue = $request->getHeader('Authorization')->getFieldValue();
$client = new Client();
$client->setUri($userInfoEndpointUrl);
$client->setMethod('POST');
$client->setOptions(['sslverifypeer' => false]);
$client->setHeaders(['Authorization' => $authorizationHeaderValue]);
$client->setOptions([
'maxredirects' => 10,
'timeout' => 30,
]);
$client->setParameterPost([]);
$response = $client->send();
$userInfo = json_decode($response->getContent(), true);
return $userInfo;
}
}
答案 0 :(得分:1)
好吧,我现在看到了 - 它实际上无法运作。执行新请求会递归地启动整个事件链并导致无限循环。
在我的情况下,为了避免多次请求我的userinfo
端点,我将调用放入工厂,并可以在其他工厂和事件监听器中使用它:
namespace MyModule;
...
class Module
{
public function onBootstrap(MvcEvent $mvcEvent)
{
...
$halPlugin->getEventManager()->attach('myeventname', function ($event) use (..., $serviceManager) {
...
$userInfo = $serviceManager->get('MyModule\\Service\\UserInfo');
...
});
...
}
...
public function getServiceConfig()
{
return array(
'factories' => array(
'MyModule\\V1\\Rest\\Foo\\FooService' => function(ServiceManager $serviceManager) {
...
$userInfo = $serviceManager->get('MyModule\\Service\\UserInfo');
...
return $fooService;
},
'MyModule\\Service\\UserInfo' => function(ServiceManager $serviceManager) {
$userInfoEndpointUrl = $serviceManager->get('Config')['user_info_endpoint_url'];
$request = $serviceManager->get('Request');
$userInfo = $this->retrieveUserInfosEndpoint($request, $userInfoEndpointUrl);
return $userInfo;
},
...
),
...
);
}
}