phalconphalcon-routing

Phalcon\Micro: Execute another controller action in action


I have a controller action which gets executed on one server. This action has to trigger two other services which can be on the same or other server (depending on the configured routes). Currently I always use HTTP requests. But if the services are on the same server I would rather like to call the appropriate controller (depending on the url, respecting custom routes) directly.

My code with requests looks like:

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);
}

Solution

  • I found a possible solution:

    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);
    }
    

    whereas RoutesToControllerMapper look like:

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