2012-10-02 21 views
9

हाय सब में,एक कस्टम ExceptionStrategy को परिभाषित ZF2 मॉड्यूल

मैं एक सप्ताह से अधिक के लिए इस मुद्दे के साथ संघर्ष कर रहे हैं और अंत में उम्मीद है कि किसी को जवाब जानता है मदद के लिए पूछना का फैसला किया।

मैं एक आवेदन पत्र है, जो डेटा विनिमय प्रारूप के रूप में Google's Protocol Buffers उपयोग कर रहा है के विकास कर रहा हूँ। मैं DrSlump के PHP implementation का उपयोग कर रहा हूं, जो कि आप डेटा के साथ क्लास इंस्टेंस को पॉप्युलेट करते हैं और फिर उन्हें बाइनरी स्ट्रिंग (या PHP ऑब्जेक्ट्स में डिकोड बाइनरी स्ट्रिंग) में क्रमबद्ध करते हैं।

मैं अपने कस्टम ProtobufStrategy जिसका selectRenderer(ViewEvent $e)ProtobufRenderer का एक उदाहरण के मामले में घटना ProtobufModel का एक उदाहरण शामिल रिटर्न लागू करने के लिए प्रबंधित किया है। रेंडरर तो $model->getOptions() बुला निर्धारित करने के लिए जो संदेश वापस ग्राहक को भेजे जाने की आवश्यकता द्वारा मॉडल से अपने कस्टम पैरामीटर निकालता है, डेटा serializes और php के लिए बाइनरी स्ट्रिंग आउटपुट: // उत्पादन

इसे और अधिक समझ बनाने के लिए के लिए, हम निम्नलिखित नमूना संदेश पर ध्यान दें: अगर मैं इस संदेश के साथ ग्राहक को जवाब चाहते थे

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 के दूसरा पैरामीटर, $ विकल्पों का उपयोग कर रहा हूँ देख सकते हैं, यह बताने के लिए जो संदेश धारावाहिक की जरूरत है। इसके बाद, जैसा कि पहले उल्लेख किया गया है, $model->getOptions() पर कॉल करके रेंडरर के अंदर निकाला जा सकता है।

अभी तक, बहुत अच्छा है। मेरे नियंत्रक कार्रवाई अपेक्षित बाइनरी डेटा आउटपुट।

हालांकि, मुझे अपवादों को संभालने में समस्याएं हैं। मेरी योजना सभी अपवादों को पकड़ने और मेरी अपवाद संदेश का एक उदाहरण है, जो इस तरह दिखता है के साथ ग्राहक के लिए प्रतिक्रिया करने के लिए किया गया था:

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 का एक उदाहरण है, जो स्पष्ट रूप से अतिरिक्त $ विकल्पों जानकारी की आवश्यकता शामिल नहीं है देता है।

इसके अलावा यह ViewModel और ProtobufModel नहीं देता है, जिसका अर्थ है कि ज़ेंड डिफ़ॉल्ट 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 में पंजीकृत हो गया है। मुझे आशा है कि मुझे ऐसी आसान चीज़ प्राप्त करने के लिए कस्टम व्यू मैनेजर जोड़ने की ज़रूरत नहीं है, लेकिन अगर मैं गलत हूं तो मुझे सही करें।

किसी भी मदद की सराहना की जाएगी!

+0

एक अच्छी तरह से लिखित, अच्छी तरह से शोध किए गए प्रश्न के लिए बधाई! – markus

उत्तर

10

सबसे आसान तरीका थोड़ा झुकाव करना है।

सबसे पहले, अपने श्रोता को ExceptionStrategy की तुलना में उच्च प्राथमिकता पर चलाने के लिए पंजीकृत करें; क्योंकि यह डिफ़ॉल्ट प्राथमिकता पर पंजीकरण करता है, इस से 1.

किसी भी प्राथमिकता उच्च का मतलब है फिर, अपने श्रोता में, इससे पहले कि आप लौटने के लिए, यदि आप एक falsy मूल्य के लिए MvcEvent में "त्रुटि" सेट सुनिश्चित करें:

$e->setError(false); 

एक बार जब आप इसे कर लेंगे, तो डिफ़ॉल्ट अपवाद स्ट्रैटजी कहेंगे, "यहां कुछ भी नहीं करना, आगे बढ़ना" और ViewModel के साथ कुछ भी करने से पहले, जल्दी वापस आएं।

आप उस पर होते हैं, तो आप भी आप स्थिति में परिणाम उदाहरण बदलने यह सुनिश्चित करना चाहिये:

$e->setResult($yourProtobufModel) 

इस रूप में यह सुनिश्चित करेंगे कि यह क्या अन्य श्रोताओं ने निरीक्षण किया जाता है।

+1

बहुत बहुत धन्यवाद! पूरी तरह से काम किया! – Andris