Domanda

. Ciao tutti,

Ho lottato con questo problema per più di una settimana e ha finalmente deciso di chiedere aiuto sperando che qualcuno conosca la risposta.

Sto sviluppando un'applicazione, che sta usando buffer del protocollo di Google come formato di scambio di dati. Sto usando il php Implementazione , che popoli le istanze di classe con i dati e poi li seriano in una stringa binaria (o decodifica stringhe binarie in oggetti PHP).

Sono riuscito a implementare il mio ProtobufStrategy personalizzato il cui selectRenderer(ViewEvent $e) restituisce un'istanza di ProtobufRenderer nel caso in cui l'evento contiene un'istanza di ProtobufModel. Il renderer estrae quindi i miei parametri personalizzati dal modello chiamando $model->getOptions() per determinare quale messaggio deve essere inviato al client, serializza i dati e emette la stringa binaria a php: // output . .

Per avere più senso, guardiamo il seguente messaggio di esempio:

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

Se volessi rispondere al cliente con questo messaggio, restituirei qualcosa del genere dalla mia azione:

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

Come puoi vedere Sto utilizzando il secondo parametro di ViewModel, $ opzioni , per dire quale messaggio deve essere serializzato. Che può quindi, come accennato in precedenza, essere estratti all'interno del renderer chiamando $model->getOptions().

Finora, così buono. I miei Azioni controller Usano i dati binari come previsto.

Tuttavia, sto avendo problemi con la gestione delle eccezioni. Il mio piano doveva catturare tutte le eccezioni e rispondere al cliente con un'istanza del mio messaggio Exception , che sembra questo:

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;
}
.

In teoria dovrebbe funzionare fuori dalla scatola, ma non lo fa. Il problema è che Zend\Mvc\View\Http\ExceptionStrategy::prepareExceptionViewModel(MvcEvent $e) restituisce un'istanza di ViewModel, che ovviamente non contiene le informazioni aggiuntive $ di cui ho bisogno.

Restituisce anche ViewModel e non ProtobufModel, il che significa che lo Zend invoca il ViewPhpRenderer predefinito emette l'eccezione come una pagina HTML.

Quello che voglio fare è Sostituire il ExceptionStrategy predefinito (e alla fine anche il RouteNotFoundStrategy) con le mie classi, che restituirebbe qualcosa del genere:

$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',
));
.

... E non riesco a trovare il modo per farlo ...

Ho provato a creare la mia classe ExceptionStrategy e alias all'IT per l'esistente ExceptionStrategy Servizio ma Zend si è lamentato del fatto che un servizio con tale nome esiste già.

Ho un sospetto che io sia sul percorso giusto con l'estensione della strategia personalizzata non riesco a trovare un modo per sovrascrivere uno predefinito.

Ho notato che il ExceptionStrategy predefinito e la console si registrano in Zend/Mvc/View/Http/ViewManager. Spero di non dover aggiungere gestori di visualizzazione personalizzati per ottenere una cosa così semplice ma per favore, correggimi se sbaglio.

Qualsiasi aiuto sarà apprezzato!

È stato utile?

Soluzione

Il modo più semplice è fare un po 'di sbavatura.

In primo luogo, registra il tuo listener per correre a una priorità più alta della eccezione;Dal momento che si registra a priorità predefinita, questo significa qualsiasi priorità superiore a 1.

Quindi, nel tuo ascoltatore, prima di tornare, assicurati di impostare "Errore" nel mvcevent in un valore falso:

$e->setError(false);
.

Una volta che lo hai fatto, l'eccezione predefinita dirà, "Niente da fare qui, muoversi" e ritorna presto, prima di fare qualsiasi cosa con il mirino.

Mentre sei a ciò, dovresti anche assicurarti di modificare l'istanza dei risultati nell'evento:

$e->setResult($yourProtobufModel)
.

Poiché questo garantirà che questo sia ciò che viene ispezionato da altri ascoltatori.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top