Intereting Posts
Пересечение многомерного массива различного размера Laravel 4 + Iron Mq: очереди запущены, но почта не отправляется Классификация изображений – определение планов этажей register_shutdown_function () все еще выводит исходное сообщение об ошибке Как вы исправляете Nginx автоматически 301 перенаправление на тот же URL с завершающим косой чертой? Используйте openssl_encrypt для замены Mcrypt для шифрования 3DES-ECB как показать миниатюры видео YouTube PHPMailer отправляет электронные письма с предупреждением: это сообщение может и не отправляться: foo@gmail.com Подробнее Интеграция доктрины в CodeIgniter 3 – ошибка сущности php удаляет дубликаты из массива pdo для предотвращения внедрения sql Еореп (); «Удаленный доступ к файлу хоста не принят» в локальном файле? CodeIgniter: как передавать значения из определенной функции в другую setAttribute для PDO с использованием драйвера ODBC? Механизировать и BeautifulSoup для PHP?

PHP: переопределение родительских методов с помощью __call

Я хотел бы скрыть родительские методы каким-то образом, чтобы метод магии __call для дочернего класса вызывается для методов, определенных для родителя. Например:

class C { function foo() { echo "foo\n"; } } class D extends C { function __call( $method, $args ) { echo "called $name\n"; } } $d = new D(); $d->foo(); // desired result: called foo // actual result: foo 

Я проверил функции rename_function и override_function, но они не работают для методов. ReflectionMethod имеет метод setAccessible, который я пытался, но это работает, только если вы используете экземпляр ReflectionMethod для вызова метода.

Предпосылки: попытка иметь прокси-класс RPC, который может использовать проверку типов PHP. Итак, если у меня есть RPCFoo, я могу использовать тип hinting или instanceof для принудительного ввода типа таким образом, чтобы я мог проверить это (экземпляр $ RPCFoo Foo).

Изменить: базовый класс должен быть использован как есть, без прокси. Это значит, что проксирование может быть частью конфигурации системы, а не кода. Подумайте о нескольких серверах с одинаковой базой кода, но о возможности назначать определенные задачи каждому. Если локальный сервер не обрабатывает запрошенную службу, загрузчик классов возвращает прокси вместо базового класса. Если локальный сервер обрабатывает запрошенную службу, он возвращает базовый класс.

Изменить снова: представленные методы являются работоспособными, но скрыть разработанный интерфейс базового класса от IDE и отражения. Я пытался сделать прокси-реализацию чистой, так что просто нужно было наследовать от базового класса и реализовать прокси-интерфейс. Чтобы поддерживать интерфейс базового класса, разработчик прокси должен будет повторно реализовать все общедоступные и защищенные методы для удаленного вызова. Затем, когда что-то обновляется в базовом классе, прокси должен также быть обновлен. В конце концов, я думаю, что я просто собираюсь идти по пути создания генератора прокси-сервера, который использует отражение для разработчика.

Спасибо за ответы!

Вы должны установить доступ к private foo :

 class C { private function foo() { echo "foo\n"; } public function __call($method, $args) { if(is_callable(array($this,$method))) { return call_user_func_array(array($this,$method), $args); } else { trigger_error("Call to undefined method '{$method}'"); } } } 
 class C { public function __call($method, $args) { return call_user_func_array(array(__CLASS__ ,$method), $args); } protected function foo() { echo "foo<br />"; } } class D extends C { function __call( $method, $args ) { echo "called $method<br/>"; } } $d = new D(); $d->foo(); $c = new C(); $c->foo(); 

Я знаю, что этот вопрос немного стар, но я получил его работу, поэтому я размещаю его здесь, чтобы помочь людям, столкнувшимся с одной и той же проблемой.

Мое решение переопределить родительские методы с помощью магического метода __call ():

 public function foo($p1, $p2, $p3) { if (get_class($this) == __CLASS__) { /* Do stuff here */ } elseif (method_exists($this, '__call')) { return call_user_func_array([$this, '__call'], ['foo', func_get_args()]); } return false; } 

Единственное ограничение состоит в том, что сам родительский класс не может иметь волшебный метод __call (), иначе он будет вызывать метод __call () из родительского класса вместо расширенного дочернего класса.