Phalcon 是否支持开箱即用的内容协商,还是有一些易于实施的解决方案?我正在搜寻“网”,但没有看到它。
谢谢!
简短的回答是否定的,感谢上帝,否则我们会有另外 100 个错误用于非主要组件:)
您可以轻松地将现有库(例如Negotiation)插入 DI,然后在整个应用程序中全局使用它。
$di->setShared('negotiator', function(){
return new \Negotiation\Negotiator();
});
$bestHeader = $di->getShared('negotiator')->getBest('en; q=0.1, fr; q=0.4, fu; q=0.9, de; q=0.2');
请记住,使用示例静态文件中的默认服务器配置(.htaccess / Nginx)将按原样提供,而不会被 Phalcon 拦截。因此,对于来自服务器的服务器文件,最好创建一个单独的控制器/操作来处理它,而不是让所有请求都通过您的应用程序。
编辑:
如果它只是让您的应用程序根据共同的区别(标头、参数、方法)发送 xml 或 json,那么您可以在没有外部框架的情况下轻松完成它。有很多策略,最简单的就是拦截Dispatcher::dispatch()
,在其中决定要返回什么内容并相应地配置视图和响应——其余的由 Phalcon 完成。
/**
* All controllers must extend the base class and actions must set result to `$this->responseContent` property,
* that value will be later converted to the appropriate form.
*/
abstract class AbstractController extends \Phalcon\Mvc\Controller
{
/**
* Response content in a common format that can be converted to either json or xml.
*
* @var array
*/
public $responseContent;
}
/**
* New dispatcher checks if the last dispatched controller has `$responseContent` property it will convert it
* to the right format, disable the view and direcly return the result.
*/
class Dispatcher extends \Phalcon\Mvc\Dispatcher
{
/**
* @inheritdoc
*/
public function dispatch()
{
$result = parent::dispatch();
$headerAccept = $this->request->getHeader('Accept');
$headerContentType = $this->request->getHeader('Content-Type');
$lastController = $this->getLastController();
// If controller is an "alien" or the response content is not provided, just return the original result.
if (!$lastController instanceof AbstractController || !isset($lastController->responseContent)) {
return $result;
}
// Decide what content format has been requested and prepare the response.
if ($headerAccept === 'application/json' && $headerContentType === 'application/json') {
$response = json_encode($lastController->responseContent);
$contentType = 'application/json';
} else {
$response = your_xml_convertion_method_call($lastController->responseContent);
$contentType = 'application/xml';
}
// Disable the view – we are not rendering anything (unless you've already disabled it globally).
$view->disable();
// Prepare the actual response object.
$response = $lastController->response
->setContent($response)
->setContentType($contentType);
// The returned value must also be set explicitly.
$this->setReturnedValue($response);
return $result;
}
}
// In your configuration you must insert the right dispatcher into DI.
$di->setShared('dispatcher', function(){
return new \The\Above\Dispatcher();
});
只是认为您可能可以使用调度循环事件来实现相同的目的。理论上的解决方案可能看起来更优雅,但我从未尝试过,所以您可能想自己尝试一下。