Поэтому я хочу иметь возможность добавлять / удалять методы класса во время выполнения. Прежде чем рассказать мне, что это ужасная оценка, возможно, но мне все равно. Причина, по которой я хочу это сделать, – это то, что я хочу, чтобы приложение было очень модульным, поэтому какой-то плагин мог расширить базовый класс и добавить к нему методы, не убивая основное приложение.
Например, скажем, у меня есть следующий класс:
class User { protected $Id; protected $Name; protected $Password; protected $PostsPerPage; }
И, скажем, какой-то плагин добавляет возможность пользователям изменять настройки видимости, добавляя к классу свойство $ Visible. Класс стал бы:
class User { protected $Id; protected $Name; protected $Password; protected $PostsPerPage; protected $Visible; }
Это может быть достигнуто с помощью __get и __set, но наиболее распространенная реализация заключается в получении и настройке генерируемых свойств среды выполнения, и было бы затруднительно скомпоновать псевдопользователи и сеттеры для каждого добавленного свойства, а также использовать __set – нет, по-моему.
Другая идея, которую я имел, заключалась в том, чтобы хранить пользовательские настройки отдельно, в другом массиве, например $ UserVisiblitySettings [userid], но это делает вещи не такими, как OO, как я хотел бы, чтобы они были.
Следующей идеей было создание вспомогательного класса, что-то вроде этого:
class UserHelper { public function SetVisiblity($user_object,value); }
Затем я мог использовать __get и __set для реализации «друзей» методов / классов, но это звучит слишком хакерски. Если бы я пошел таким путем, можно было бы просто перегрузить __call, __get и __set. Кроме того, я не уверен, что это хорошая оценка ООП, и это выглядело бы уродливо.
Последняя идея, которую я имел, заключалась в том, чтобы иметь некоторую функцию для динамического создания классов во время выполнения с помощью eval () (это единственное допустимое использование eval, которое я мог бы придумать). В принципе, получите определение класса из файла, сделайте несколько простых поиска скобок, чтобы найти открывающие и закрывающие скобки класса и отправить его в eval.
Использование runkit не может быть и речи, поскольку оно устарело, и я не хочу, чтобы пользователь не устанавливал какое-то расширение.
Когда я смотрю на свои идеи, самым простым и менее интенсивным CPU становится перегрузка _call и добавление способа регистрации методов в классе.
Пожалуйста, обратите внимание на любые мысли, которые не «не делают этого».
Расширение RunKit может сделать это ( runkit_method_add()
и т. Д.)
Однако это экспериментальное расширение, и вы уже нацелены на ногу …
У вас есть другие возможности:
__get()
и __call()
class Plugin extends BaseImplementation
и имеет фабричный экземпляр Plugin
вместо BaseImplementation
). Zend Plugin Loader делает что-то вроде этого. $this->plugin->onFoo()
). Для этого есть библиотека . PHP этого не допускает. Это может быть динамический язык в других отношениях, но система классов преднамеренно ограничивает. Вы можете установить расширение runkit , которое меняет язык, чтобы позволить насмехаться с классами во время выполнения (но тогда вы больше не используете простой PHP), или вы можете использовать магические методы для имитации.
Вы можете переопределить класс, но я не знаю, можете ли его перезагрузить в том же запросе. некоторые изменения поведения могут быть достигнуты с помощью шаблона проектирования медиатора (диспетчера событий Symfony), но вам нужно заранее знать точки расширения, а также события пожара / сообщения, которые будут улавливаться расширяющимся классом в будущем.
если вы можете дождаться следующего запроса и очистить кеш, если он у вас есть. Я сделал инструмент, который мог бы вам помочь. SourceEditor
Здесь также есть ответы на аналогичный вопрос, где я помещаю примеры кода. Как создать или изменить класс PHP во время выполнения?