【问题标题】:Phalcon\Micro: Execute another controller action in actionPhalcon\Micro:执行另一个控制器动作
【发布时间】:2017-05-09 10:46:49
【问题描述】:

我有一个在一台服务器上执行的控制器操作。此操作必须触发两个其他服务,这些服务可以在同一台服务器或其他服务器上(取决于配置的路由)。目前我总是使用 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);
}

【问题讨论】:

  • 那么如果本地实例上不存在路由,如何使用HTTP请求呢?这是你的问题吗?
  • 但是 action 是一个 action,http 端点,如果你希望它只是泛型方法然后将它移动到一些泛型方法,真的看不出问题。
  • @Juri 问题是我的路由器根据 url 路由到不同的控制器。如果我想调用适当的控制器和方法,我将不得不复制路由器的行为。我希望 Phalcon 已经以某种方式实现了这一点(请参阅我更新的伪代码)
  • 您能否补充一些说明。当您说同一台服务器时,您是指同一台服务器不同的应用程序吗?还是相同的应用程序?如果相同的应用程序,那么您不能转发到相应的控制器。如果是不同的应用程序,那么可以转发的钩子控制器怎么样?或者使用带有后台任务的 beanstalkd 消息队列来产生和消费?
  • 是的,只需将应该在两个操作中执行的代码移动到单独的代码中。有$this->dispatcher->forward,但顾名思义,它将动作执行转发给其他动作。就像 return here 实际上不会做任何事情。

标签: phalcon phalcon-routing


【解决方案1】:

我找到了一个可能的解决方案:

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']];
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-11
    相关资源
    最近更新 更多