Изменение класса выполнения PHP

Поэтому я хочу иметь возможность добавлять / удалять методы класса во время выполнения. Прежде чем рассказать мне, что это ужасная оценка, возможно, но мне все равно. Причина, по которой я хочу это сделать, – это то, что я хочу, чтобы приложение было очень модульным, поэтому какой-то плагин мог расширить базовый класс и добавить к нему методы, не убивая основное приложение.

Например, скажем, у меня есть следующий класс:

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 и добавление способа регистрации методов в классе.

Пожалуйста, обратите внимание на любые мысли, которые не «не делают этого».

Solutions Collecting From Web of "Изменение класса выполнения PHP"

Расширение RunKit может сделать это ( runkit_method_add() и т. Д.)

Однако это экспериментальное расширение, и вы уже нацелены на ногу …

У вас есть другие возможности:

  • Эмулируйте новые поля и методы с помощью __get() и __call()
  • Используйте подклассы и Factory pattern ( class Plugin extends BaseImplementation и имеет фабричный экземпляр Plugin вместо BaseImplementation ). Zend Plugin Loader делает что-то вроде этого.
    Это решение с наименьшими затратами, но также ограничено одним плагином, распространяющимся на один класс.
  • Добавьте крючки и используйте делегирование (шаблон стратегии) ​​( $this->plugin->onFoo() ). Для этого есть библиотека .

PHP этого не допускает. Это может быть динамический язык в других отношениях, но система классов преднамеренно ограничивает. Вы можете установить расширение runkit , которое меняет язык, чтобы позволить насмехаться с классами во время выполнения (но тогда вы больше не используете простой PHP), или вы можете использовать магические методы для имитации.

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

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

Здесь также есть ответы на аналогичный вопрос, где я помещаю примеры кода. Как создать или изменить класс PHP во время выполнения?