Frage

Hallo zusammen,

Ich kämpfe seit mehr als einer Woche mit diesem Problem und beschloss schließlich, um Hilfe zu bitten, in der Hoffnung, dass jemand die Antwort kennt.

Ich entwickle eine Anwendung, die verwendet wird Die Protokollpuffer von Google als Datenaustauschformat.Ich verwende DrSlumps PHP Implementierung, mit dem Sie Klasseninstanzen mit Daten füllen und diese dann in eine Binärzeichenfolge serialisieren (oder Binärzeichenfolgen in PHP-Objekte dekodieren) können.

Ich habe es geschafft, meinen Brauch umzusetzen ProtobufStrategy wessen selectRenderer(ViewEvent $e) gibt eine Instanz von zurück ProtobufRenderer falls das Ereignis eine Instanz von enthält ProtobufModel.Der Renderer extrahiert dann durch Aufruf meine benutzerdefinierten Parameter aus dem Modell $model->getOptions() Um zu bestimmen, welche Nachricht an den Client zurückgesendet werden muss, serialisiert er die Daten und gibt die Binärzeichenfolge an aus php://Ausgabe.

Um es sinnvoller zu machen, schauen wir uns die folgende Beispielnachricht an:

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

Wenn ich dem Kunden mit dieser Nachricht antworten wollte, würde ich von meiner Aktion etwa Folgendes zurückgeben:

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

Wie Sie sehen, nutze ich ViewModel's zweiter Parameter, $optionen, um anzugeben, welche Nachricht serialisiert werden muss.Das kann dann, wie bereits erwähnt, durch einen Aufruf innerhalb des Renderers extrahiert werden $model->getOptions().

So weit, ist es gut.Meine Controller-Aktionen geben wie erwartet Binärdaten aus.

Allerdings habe ich Probleme mit der Behandlung von Ausnahmen.Mein Plan war es, alle Ausnahmen abzufangen und dem Kunden mit einer Instanz von mir zu antworten Ausnahme Nachricht, die so aussieht:

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

Theoretisch sollte es sofort funktionieren, aber das ist nicht der Fall.Das Problem ist das Zend\Mvc\View\Http\ExceptionStrategy::prepareExceptionViewModel(MvcEvent $e) gibt eine Instanz von zurück ViewModel, was den Zusatz offensichtlich nicht enthält $optionen Informationen, die ich brauche.

Es kehrt auch zurück ViewModel und nicht ProtobufModel, was bedeutet, dass Zend die Standardeinstellung aufruft ViewPhpRenderer und gibt die Ausnahme als HTML-Seite aus.

Was ich tun möchte ist Ersetzen Sie die Standardeinstellung ExceptionStrategy (und schließlich auch die RouteNotFoundStrategy) mit meinen eigenen Klassen, die etwa Folgendes zurückgeben würden:

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

... und ich finde den Weg dazu nicht ...

Ich habe versucht, mein eigenes zu erstellen ExceptionStrategy Klasse und alias es auf die vorhandene Ausnahmestrategie Dienst, aber Zend hat sich darüber beschwert, dass ein Dienst mit diesem Namen bereits existiert.

Ich habe den Verdacht, dass ich mit der benutzerdefinierten Strategieerweiterung auf dem richtigen Weg bin. Ich finde keine Möglichkeit, die Standarderweiterung zu überschreiben.

Mir ist aufgefallen, dass die Standardeinstellung ExceptionStrategy und die Konsole, in der man sich registriert Zend/Mvc/View/Http/ViewManager.Ich hoffe, dass ich keine benutzerdefinierten Ansichtsmanager hinzufügen muss, um so eine einfache Sache zu erreichen, aber korrigieren Sie mich bitte, wenn ich falsch liege.

Jede Hilfe wird geschätzt!

War es hilfreich?

Lösung

Der einfachste Weg ist, ein wenig zu fummeln.

Registrieren Sie zunächst Ihren Listener so, dass er mit einer höheren Priorität als der ExceptionStrategy ausgeführt wird.Da es mit der Standardpriorität registriert wird, bedeutet dies jede Priorität höher als 1.

Stellen Sie dann in Ihrem Listener vor Ihrer Rückkehr sicher, dass Sie den „Fehler“ im MvcEvent auf einen falschen Wert setzen:

$e->setError(false);

Sobald Sie dies getan haben, sagt die standardmäßige ExceptionStrategy: „Hier gibt es nichts zu tun, machen Sie weiter“ und kehren Sie vorzeitig zurück, bevor Sie etwas mit dem ViewModel tun.

Wenn Sie schon dabei sind, sollten Sie auch sicherstellen, dass Sie die Ergebnisinstanz im Ereignis ändern:

$e->setResult($yourProtobufModel)

da dadurch sichergestellt wird, dass dies auch von anderen Zuhörern überprüft wird.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top