سؤال

أهلاً بكم،

لقد كنت أعاني من هذه المشكلة منذ أكثر من أسبوع وقررت أخيرًا أن أطلب المساعدة على أمل أن يعرف أحد الإجابة.

أقوم بتطوير تطبيق يستخدم مخازن بروتوكول جوجل كتنسيق تبادل البيانات.أنا أستخدم PHP الخاص بـ DrSlump تطبيق, ، والذي يتيح لك ملء مثيلات الفئة بالبيانات ثم إجراء تسلسل لها في سلسلة ثنائية (أو فك تشفير السلاسل الثنائية إلى كائنات 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المعلمة الثانية , خيارات $, ، لمعرفة الرسالة التي يجب إجراء تسلسل لها.ويمكن بعد ذلك، كما ذكرنا سابقًا، استخراج ذلك داخل العارض عن طريق الاتصال $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, ، مما يعني أن 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 فئة والاسم المستعار إلى القائمة استراتيجية الاستثناء الخدمة ولكن Zend اشتكى من وجود خدمة بهذا الاسم بالفعل.

لدي شك في أنني أسير على الطريق الصحيح مع ملحق الإستراتيجية المخصصة ولا يمكنني العثور على طريقة لتجاوز الامتداد الافتراضي.

لقد لاحظت أن الافتراضي ExceptionStrategy ويتم تسجيل وحدة التحكم فيها Zend/Mvc/View/Http/ViewManager.آمل ألا أضطر إلى إضافة مديري عرض مخصص لتحقيق مثل هذا الشيء البسيط ولكن من فضلك صححني إذا كنت مخطئًا.

سيكون موضع تقدير أي مساعدة!

هل كانت مفيدة؟

المحلول

أسهل طريقة هي عمل القليل من الحلوى.

أولاً، قم بتسجيل المستمع الخاص بك للتشغيل بأولوية أعلى من ExceptionStrategy؛وبما أنه يسجل في الأولوية الافتراضية، فهذا يعني أي أولوية أعلى من 1.

ثم، في المستمع الخاص بك، قبل العودة، تأكد من تعيين "الخطأ" في MvcEvent إلى قيمة خاطئة:

$e->setError(false);

بمجرد الانتهاء من ذلك، ستقول استراتيجية الاستثناء الافتراضية، "لا يوجد شيء يجب القيام به هنا، تحرك للأمام" ثم عد مبكرًا، قبل القيام بأي شيء باستخدام ViewModel.

أثناء قيامك بذلك، يجب عليك أيضًا التأكد من تغيير مثيل النتيجة في الحدث:

$e->setResult($yourProtobufModel)

لأن هذا سيضمن أن هذا هو ما يتم فحصه من قبل المستمعين الآخرين.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top