Symfony 2 - 在服务内处理内核请求(来自另一个应用程序)
首先,我想说我发现 Symfony2 是一个了不起的框架,所以我正在使用 FOSRestBundle 等创建一个 RESTful API.但我的目标不是仅支持一个带有 API 的 symfony2 应用程序,我需要多个其他应用程序symfony2 应用程序与 API 交互.我确实可以使用 cURL 来做到这一点,并且只向 API 发出普通的 http 请求,但是因为 API 总是与所有其他项目在同一台服务器上,我想直接通过它的内核处理 API 请求(所以没有卷曲).这当然带来了惊人的速度提升和更少的资源使用.
First I would like to say I find Symfony2 an amazing framework, so I'm creating a RESTful API with it using FOSRestBundle etc. But I'm not aiming for supporting only one symfony2 application with the API, I need multiple other symfony2 applications to interact with the API. I could indeed do this with the use of cURL and just make plain http requests to the API, but because the API is always on the same server as all the other projects I would like to handle the API requests directly trough it's Kernel (so no cURL). This comes with an amazing speed boost ofcourse and also less use of resources.
所以,为了实现这一点,我首先想到的是简单地从它的目的地要求 AppKernel,就像这样:
So, to make this happen, I first thought about simply requiring the AppKernel from it's destination, like so:
require_once '/path/to/external/AppKernel.php';
然后我将创建一个 AppKernel 实例并在此处处理子请求".但是,我立即收到错误消息,说无法加载某些包等.这是合乎逻辑的,因为我只需要 AppKernel 文件,而不是依赖项.所以我包含了 API 项目的自动加载器 (/app/autoload.php),但这并没有解决问题,我遇到了与重新声明的类/函数等相关的错误.
Then I would create an instance of AppKernel and handle the "sub-request" in here. But then, I instantly got errors, saying some bundles could not be loaded etc. which is logical because I only required the AppKernel file, not it's dependencies. So I included the autoloader of the API project (/app/autoload.php), but this did not resolve the problems, I got errors related to redeclared classes/functions etc.
这将给出如下内容:
require_once '/path/to/external/AppKernel.php';
$class = 'NamespaceAppKernel';
// 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)的更好方法.
I think I'm doing it all wrong with trying to handle it trough the AppKernel, maybe someone knows a better way to make a call to a external Symfony2 project (without cURL).
我真的希望有人能帮助我!
I really hope somebody could help me out!
史蒂芬
推荐答案
我已经设法让它工作了 :) 我检查了路由文件,发现请求在请求前面缺少一个正斜杠 (/)里.这解释了 404 未找到.所以我的工作 KernelRequestHandler 实现现在是:
I've managed to get it working :) I checked the routing files, and saw that the request was missing a forward slash (/) infront of the request uri. That explained the 404 not found. So my working KernelRequestHandler implementation is now:
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();
}
}
当然,这只是一个工作示例,我会以更好的方式实施此策略.好吧,看看寻找相同答案的人吧!
Ofcourse this is just a working example, I'm going to implement this strategy in a better way. Well, good look to the one looking for the same answer!
我认为最好的方法是拥有 2 个自动加载器,一个用于主 sf2 应用程序,另一个用于 API.这样两个项目的供应商都会自动加载.
I think the best way is to have 2 autoloaders, one for the main sf2 application and one for the API in this case. This way the vendors of both projects get autoloaded.
相关文章