1

Phalcon 是否支持开箱即用的内容协商,还是有一些易于实施的解决方案?我正在搜寻“网”,但没有看到它。

谢谢!

4

1 回答 1

1

简短的回答是否定的,感谢上帝,否则我们会有另外 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();
});

只是认为您可能可以使用调度循环事件来实现相同的目的。理论上的解决方案可能看起来更优雅,但我从未尝试过,所以您可能想自己尝试一下。

于 2014-09-03T10:04:52.617 回答