بي أتش بي:رد الاتصال عند الدخول/الخروج من أساليب الفصل؟

StackOverflow https://stackoverflow.com/questions/288877

سؤال

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

لا بد لي الآن من الاتصال بـ Logger::logEntry() وLogger::logExit() بكل طريقة لتحقيق ذلك.أحب ألا أضطر إلى القيام بذلك:

class TestClass {
    public function tester($arg) {
        Logger::logEntry();
        Logger::info('Parameter $arg => ' . $arg);

        // Do some stuff...

        Logger::logExit();
    }
}
هل كانت مفيدة؟

المحلول

استخدم فئة المجمع.هذه الطريقة لها الفوائد التالية:

  • لا حاجة لتغيير بنية الفصل/توقيعات الطريقة الأساسية
  • تغيير التسجيل؟فقط قم بتحديث هذه الفئة
  • تحديث استدعاءات الكائنات مقابل إدخال التعليمات البرمجية في كل فئة تريد تسجيلها

.

class LogWatch {
    function __construct($class)    {
        $this->obj  =   $class;
    }

    function __call($method, $args) {
        if (in_array($method, get_class_methods($this->obj) ) ) {
            Logger::logEntry();
            Logger::info('Parameter '.implode(', ', $args) );

            call_user_func_array(array($this->obj, $method), $args);

            Logger::logExit();

        } else {
            throw new BadMethodCallException();
        }
    }
}

$test = new LogWatch(new TestClass() );
$test->tester();

// you can use instances of `LogWatch()` just like your watched class
// including passing appropriate params:
$test->tester($param1, $param2);

نصائح أخرى

إذا كنت تريد القيام بتسجيل الوظائف من أجل تصحيح الأخطاء، فقد ترغب في النظر في ملحق Xdebug.لا توجد طريقة جيدة لاعتراض استدعاءات الوظائف في وقت التشغيل، وأي اعتراض تلقائي سيضيف أعباء كبيرة على وقت التشغيل.

باستخدام XDebug، يمكنك بدلاً من ذلك تشغيله حسب الحاجة، بالإضافة إلى الحصول على الكثير من الأشياء الأخرى

(وبالتالي يتم استخدام XDebug مع PHPUnit لإجراء اختبار الوحدة وتحليل التغطية.)

المشكلة مع __call

__call قد يبدو حلاً ممتعًا للمشكلة، ولكن يوجد 3 مشاكل مع هذا، وهي

  • نفقات تنفيذ كبيرة.ما تفعله __call --> call_user_func_array ، والذي لن يضيف حرفيًا واحدًا، بل اثنين استدعاءات الدالة لكل تنفيذ.

  • تصبح الآثار الخلفية غير قابلة للفك:يتم فقدان الوظيفة الفعلية التي كنت تحاول الاتصال بها في بحر من __call وcall_user_func_array مما يجعل التتبع الخلفي صعبًا للغاية، خاصة إذا كانت التتبعات الخلفية الخاصة بك تأتي مع قوائمها الجدلية المضمنة.

  • وظائف مخفية غبية:ستعود إلى نمط PHP4 "لإخفاء" الوظائف عن طريق إضافة بادئة لها بـ _ لمنع المستخدم من الاتصال بها مباشرة أو رؤيتها، لأنه إذا تم تسمية اسم الوظيفة بما لا يريده، فلن يتم تشغيل __call، لذلك لقد حصلت بالفعل على فصل كامل مليء بأسماء الوظائف الرهيبة حقًا، والتي سيميل المطورون إلى الاتصال بها مباشرة على أي حال في أماكن مختلفة.(وإذا كنت تريد التخلص من __call لاحقًا، فسيتعين عليك إعادة تسمية كل هذه الوظائف حتى لا تكسر الكود!)

وبالتالي، إذا كنت تستخدم تعليمات برمجية php لتنفيذ ذلك، فسيؤدي ذلك إلى إنشاء تعليمات برمجية فظيعة للغاية، والتي سوف يفعلها أي مستخدم مستقبلي لقاعدة التعليمات البرمجية الخاصة بك لا تريد العمل مع.من الأفضل أن تحصل على شيء (مثل Xdebug) يمكن إضافته بشفافية عندما تحتاج إليه، مما يوفر تلويثًا كبيرًا للتعليمات البرمجية الخاصة بك.

هل يمكن استخدام وظيفة __call السحر. يحصل يطلق عليه عندما تتطابق أي وظائف هذا الاسم. إعادة تسمية الطرق الخاصة بك لتكون مسبوقة ب شيء، (على سبيل المثال: تسطير)، واختياريا مجموعة منهم إلى القطاع الخاص / محمية

class TestClass {
    public function __call($function, $args) {
        Logger::logEntry();
        Logger::info('Parameters: ' . implode(", ", $args);

        $localFunc = "_" . $function;
        $return = $this->$localFunc($args);

        Logger::logExit();

        return $return;
    }

    private function _tester() {
        // do stuff...
        return "tester called";
    }
}

 $t = new TestClass();
 echo $t->tester();
 // "tester called"
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top