【问题标题】:Define a custom ExceptionStrategy in a ZF2 module在 ZF2 模块中定义自定义 ExceptionStrategy
【发布时间】:2012-09-23 12:16:34
【问题描述】:

大家好,

我已经为这个问题苦苦挣扎了一个多星期,最后决定寻求帮助,希望有人知道答案。

我正在开发一个应用程序,它使用Google's Protocol Buffers 作为数据交换格式。我正在使用 DrSlump 的 PHP implementation,它可以让您使用数据填充类实例,然后将它们序列化为二进制字符串(或将二进制字符串解码为 PHP 对象)。

我已经成功实现了我的自定义ProtobufStrategy,其selectRenderer(ViewEvent $e) 返回ProtobufRenderer 的实例,以防事件包含ProtobufModel 的实例。渲染器然后通过调用$model->getOptions() 从模型中提取我的自定义参数以确定需要将哪些消息发送回客户端,序列化数据并将二进制字符串输出到php://output

为了更有意义,让我们看一下以下示例消息:

message SearchRequest {
    required string query = 1;
    optional int32 page_number = 2;
    optional int32 result_per_page = 3;
}

如果我想用这条消息回复客户,我会从我的操作中返回如下内容:

public function getSearchRequestAction()
{
    [..]
    $data = array(
        'query'           => 'my query',
        'page_number'     => 3,
        'result_per_page' => 20,
    );
    return new ProtobufModel($data, array(
        'message' => 'MyNamespace\Protobuf\SearchRequest',
    ));
}

如您所见,我正在利用ViewModel 的第二个参数$options 来判断需要序列化的消息。然后,如前所述,可以通过调用 $model->getOptions() 在渲染器中提取它。

到目前为止,一切都很好。我的控制器操作按预期输出二进制数据。

但是,我在处理异常时遇到了问题。我的计划是捕获所有异常并使用我的 Exception 消息的实例响应客户端,如下所示:

message Exception {
    optional string message = 1;
    optional int32 code = 2;
    optional string file = 3;
    optional uint32 line = 4;
    optional string trace = 5;
    optional Exception previous = 6;
}

理论上它应该开箱即用,但事实并非如此。问题是Zend\Mvc\View\Http\ExceptionStrategy::prepareExceptionViewModel(MvcEvent $e) 返回了ViewModel 的一个实例,它显然不包含我需要的其他$options 信息。

它还返回ViewModel 而不是ProtobufModel,这意味着 Zend 调用默认的ViewPhpRenderer 并将异常输出为 HTML 页面。

我想要做的是用我自己的类替换默认的ExceptionStrategy(最终还有RouteNotFoundStrategy),这将返回如下内容:

$data = array(
    'message'  => $e->getMessage(),
    'code'     => $e->getCode(),
    'file'     => $e->getFile(),
    'line'     => $e->getLine(),
    'trace'    => $e->getTraceAsString(),
    'previous' => $e->getPrevious(),
);
return new ProtobufModel($data, array(
    'message' => 'MyNamespace\Protobuf\Exception',
));

...我找不到方法...

我尝试创建自己的 ExceptionStrategy 类并将其别名为现有的 ExceptionStrategy 服务,但 Zend 抱怨已经存在具有此类名称的服务。

我怀疑我在自定义策略扩展的正确路径上找不到覆盖默认策略的方法。

我注意到默认的ExceptionStrategy 和控制台之一在Zend/Mvc/View/Http/ViewManager 中注册。我希望我不必添加自定义视图管理器来实现这么简单的事情,但如果我错了,请纠正我。

任何帮助将不胜感激!

【问题讨论】:

  • 恭喜您提出了一个写得很好、经过深入研究的问题!

标签: php exception-handling module zend-framework2


【解决方案1】:

最简单的方法是做一些捏造。

首先,注册您的侦听器以比 ExceptionStrategy 更高的优先级运行;因为它以默认优先级注册,这意味着任何高于 1 的优先级。

然后,在您的侦听器中,在您返回之前,请确保将 MvcEvent 中的“错误”设置为虚假值:

$e->setError(false);

一旦你这样做了,默认的 ExceptionStrategy 会说,“这里没什么可做的,继续前进”并提前返回,然后再对 ViewModel 做任何事情。

当您使用它时,您还应该确保更改事件中的结果实例:

$e->setResult($yourProtobufModel)

因为这将确保这是由其他侦听器检查的内容。

【讨论】:

  • 非常感谢!完美运行!
猜你喜欢
  • 2013-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-24
  • 2020-06-24
相关资源
最近更新 更多