【问题标题】:Symfony 2 - Handle a Kernel request (from another app) inside a serviceSymfony 2 - 在服务中处理内核请求(来自另一个应用程序)
【发布时间】:2013-12-02 09:05:39
【问题描述】:

首先我想说我发现 Symfony2 是一个了不起的框架,所以我正在使用 FOSRestBundle 等创建一个 RESTful API。但我的目标不是只支持一个带有 API 的 symfony2 应用程序,我需要多个其他应用程序symfony2 应用程序与 API 交互。我确实可以使用 cURL 来做到这一点,只需向 API 发出普通的 http 请求,但是因为 API 总是与所有其他项目在同一台服务器上,我想直接通过它的内核处理 API 请求(所以没有卷曲)。当然,这会带来惊人的速度提升,同时也减少了资源的使用。

所以,为了实现这一点,我首先想到的是简单地从其目的地要求 AppKernel,如下所示:

require_once '/path/to/external/AppKernel.php';

然后我会创建一个 AppKernel 的实例并在这里处理“子请求”。但是随后,我立即收到错误,说无法加载某些包等。这是合乎逻辑的,因为我只需要 AppKernel 文件,而不是依赖项。所以我包含了 API 项目的自动加载器(/app/autoload.php),但这并没有解决问题,我得到了与重新声明的类/函数等相关的错误。

这会给出这样的结果:

require_once '/path/to/external/AppKernel.php';
$class = 'Namespace\AppKernel';

// I tried this, but this does not work...
$loader = require_once $path . '/autoload.php';

/**
  * @var HttpKernel $kernel
  */
$kernel = new $class('dev', true);

// $request contains a custom Request object created with 'Request::create()'
$response = $kernel->handle($request);
$response->send();

$kernel->terminate($request, $response);

return $response;

我认为我在尝试通过 AppKernel 处理它时做错了,也许有人知道更好的方法来调用外部 Symfony2 项目(没有 cURL)。

我真的希望有人可以帮助我!

史蒂芬

【问题讨论】:

    标签: php symfony curl request kernel


    【解决方案1】:

    我已经设法让它工作了 :) 我检查了路由文件,发现请求缺少请求 uri 前面的正斜杠 (/)。这解释了找不到 404。所以我的工作 KernelRequestHandler 实现现在是:

    class KernelRequestHandler implements RequestHandlerInterface
    {
        private static $kernel;
    
        /**
         * Get ApiKernel instance
         *
         * @param $class
         * @return mixed
         */
        public function getKernel($class)
        {
            if (!self::$kernel) {
                self::$kernel = new $class('prod', true);
            }
    
            return self::$kernel;
        }
    
        /**
         * @param Request $request
         * @param array $endpoints
         * @return mixed
         * @throws InvalidConfigurationException
         */
        public function handle(Request $request, array $endpoints)
        {
            require_once $endpoints['kernel']['path'];
    
            if (!isset($endpoints['kernel']['class'])) {
                throw new InvalidConfigurationException(sprintf("No class name found for instantiating kernel. Client: '%s'", $this->getName()));
            }
    
            $class = $endpoints['kernel']['class'];
    
            $path = realpath(dirname($endpoints['kernel']['path']));
    
            // Get Class Loader
            $loader = $_GLOBALS['loader'];
    
            // Add src folder to fallback dirs
            $loader->add(null, array(realpath($path . '/../src')));
    
            $class = '\ApiKernel';
    
            /**
             * @var Kernel $kernel
             */
            $kernel = $this->getKernel($class);
    
            $response = $kernel->handle($request);
    
            return $response->getContent();
        }
    }
    

    当然,这只是一个工作示例,我将以更好的方式实施此策略。好吧,寻找相同答案的人好好看看!

    编辑:

    我认为最好的方法是拥有 2 个自动加载器,一个用于主 sf2 应用程序,一个用于 API 在这种情况下。这样,两个项目的供应商都会自动加载。

    【讨论】:

    • 您最终是否在控制器中保留了这种引用自动加载器的方法? I have a need for this as well,但 the answers 在您的另一个问题上对此策略非常消极,所以我想知道您是否找到了更好的解决方案。顺便说一句,您是如何创建两个自动装载机的?
    • @ChadwickMeyer 嘿,我最终将我的另一个库的 autoload.php 文件添加到我的 symfony 应用程序的 app/autoload.php 文件中。这对你有帮助吗?
    • 不是真的:P 我不明白您合并到一个文件中的代码是什么。在我知道有关站点的某些数据之后,我需要在控制器中动态修改命名空间。所以我正在使用 $GLOBALS['loader'] 方法 ATM,但正在寻找其他想法。干杯。
    猜你喜欢
    • 1970-01-01
    • 2011-05-10
    • 1970-01-01
    • 1970-01-01
    • 2013-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多