Phalcon\Micro: 执行另一个controller action in action
Phalcon\Micro: Execute another controller action in action
我有一个在一台服务器上执行的控制器操作。此操作必须触发可以在同一台服务器或其他服务器上的其他两个服务(取决于配置的路由)。目前我总是使用 HTTP 请求。但是如果服务在同一台服务器上,我宁愿直接调用适当的控制器(取决于 url,尊重自定义路由)。
我的请求代码如下:
public function buildMultiple($platform, $name, $limit = null, $offset = null) {
$config = $this->getDI()->get('config');
$workerUrl = "{$config->application->WorkerUrl}/$platform/$name/compute/multiple/$limit/$offset";
$response = HttpRequest::get($workerUrl);
$data = json_decode($response)->data;
$clientUrl = "{$config->application->ClientUrl}/$platform/$name/update/multiple";
//TODO if the routes for the client are activated on this server then directly execute the controller
//if($config->application->ClientRoutes) {
// pseudocode:
// $cont = $this->router->getControllerFromUri($clientUrl);
// $result = $this->dispatcher($cont)->call($params, $postData);
// return $result;
//}
// else:
return HttpRequest::post($clientUrl, $data);
}
我找到了一个可能的解决方案:
public function buildMultiple($platform, $name, $limit = null, $offset = null) {
$workerUrl = "/$platform/$name/compute/multiple/$limit/$offset";
if($config->application->mviewWorkerRoutes) {
$response = RoutesToControllerMapper::call($this, $workerUrl, [$platform, $name, $limit, $offset]);
$data = $response['data'];
}
else {
$response = HttpRequest::get($config->application->mviewWorkerUrl.$workerUrl, ['changed' => $changedFields]);
$data = json_decode($response)->data;
}
$clientUrl = "/$platform/$name/update/multiple";
return $config->application->mviewClientRoutes ?
RoutesToControllerMapper::call($this, $clientUrl, [$platform, $name, $data]) :
HttpRequest::post($config->application->mviewClientUrl.$clientUrl, $data);
}
而 RoutesToControllerMapper 看起来像:
class RoutesToControllerMapper
{
public static function call($controller, $url, $arguments) {
/** @var Micro $app */
$app = $controller->getDI()->getApplication();
/** @var Micro\LazyLoader $loader */
list($loader, $method) = RoutesToControllerMapper::map($app, $url);
return $loader->callMethod($method, $arguments);
}
/**
* @param Micro $app
*/
public static function map($app, $uri) {
foreach($app->getRouter()->getRoutes() as $route) {
if(preg_match($route->getCompiledPattern(), $uri) === 1) {
$lastMatchedRoute = $route;
}
}
if(!isset($lastMatchedRoute)) {
return null;
}
$handler = $app->getHandlers()[$lastMatchedRoute->getRouteId()];
/** @var Micro\LazyLoader $lazyLoader */
$lazyLoader = $handler[0];
return [$lazyLoader, $handler['1']];
}
}
我有一个在一台服务器上执行的控制器操作。此操作必须触发可以在同一台服务器或其他服务器上的其他两个服务(取决于配置的路由)。目前我总是使用 HTTP 请求。但是如果服务在同一台服务器上,我宁愿直接调用适当的控制器(取决于 url,尊重自定义路由)。
我的请求代码如下:
public function buildMultiple($platform, $name, $limit = null, $offset = null) {
$config = $this->getDI()->get('config');
$workerUrl = "{$config->application->WorkerUrl}/$platform/$name/compute/multiple/$limit/$offset";
$response = HttpRequest::get($workerUrl);
$data = json_decode($response)->data;
$clientUrl = "{$config->application->ClientUrl}/$platform/$name/update/multiple";
//TODO if the routes for the client are activated on this server then directly execute the controller
//if($config->application->ClientRoutes) {
// pseudocode:
// $cont = $this->router->getControllerFromUri($clientUrl);
// $result = $this->dispatcher($cont)->call($params, $postData);
// return $result;
//}
// else:
return HttpRequest::post($clientUrl, $data);
}
我找到了一个可能的解决方案:
public function buildMultiple($platform, $name, $limit = null, $offset = null) {
$workerUrl = "/$platform/$name/compute/multiple/$limit/$offset";
if($config->application->mviewWorkerRoutes) {
$response = RoutesToControllerMapper::call($this, $workerUrl, [$platform, $name, $limit, $offset]);
$data = $response['data'];
}
else {
$response = HttpRequest::get($config->application->mviewWorkerUrl.$workerUrl, ['changed' => $changedFields]);
$data = json_decode($response)->data;
}
$clientUrl = "/$platform/$name/update/multiple";
return $config->application->mviewClientRoutes ?
RoutesToControllerMapper::call($this, $clientUrl, [$platform, $name, $data]) :
HttpRequest::post($config->application->mviewClientUrl.$clientUrl, $data);
}
而 RoutesToControllerMapper 看起来像:
class RoutesToControllerMapper
{
public static function call($controller, $url, $arguments) {
/** @var Micro $app */
$app = $controller->getDI()->getApplication();
/** @var Micro\LazyLoader $loader */
list($loader, $method) = RoutesToControllerMapper::map($app, $url);
return $loader->callMethod($method, $arguments);
}
/**
* @param Micro $app
*/
public static function map($app, $uri) {
foreach($app->getRouter()->getRoutes() as $route) {
if(preg_match($route->getCompiledPattern(), $uri) === 1) {
$lastMatchedRoute = $route;
}
}
if(!isset($lastMatchedRoute)) {
return null;
}
$handler = $app->getHandlers()[$lastMatchedRoute->getRouteId()];
/** @var Micro\LazyLoader $lazyLoader */
$lazyLoader = $handler[0];
return [$lazyLoader, $handler['1']];
}
}