我想为我的代码编写一种“插件/模块”系统,如果我可以在定义之后将其“添加”到类中,它会更容易。
例如,像这样:
class foo {
public function a() {
return 'b';
}
}
有班级。现在我想在定义之后添加另一个函数/变量/ const。
我意识到这可能是不可能的,但我需要确认。
答案 0 :(得分:5)
不,您无法在运行时向已定义的类添加方法。
但您可以使用__call/__callStatic
魔术方法创建类似的功能。
Class Extendable {
private $handlers = array();
public function registerHandler($handler) {
$this->handlers[] = $handler;
}
public function __call($method, $arguments) {
foreach ($this->handlers as $handler) {
if (method_exists($handler, $method)) {
return call_user_func_array(
array($handler, $method),
$arguments
);
}
}
}
}
Class myclass extends Extendable {
public function foo() {
echo 'foo';
}
}
CLass myclass2 {
public function bar() {
echo 'bar';
}
}
$myclass = new myclass();
$myclass->registerHandler(new myclass2());
$myclass->foo(); // prints 'foo'
echo "\n";
$myclass->bar(); // prints 'bar'
echo "\n";
此解决方案非常有限,但可能适用于您
答案 1 :(得分:3)
要添加/更改类在运行时的行为方式,您应该使用装饰器和/或策略。这是采用任何魔术方法或猴子补丁的首选OO方法。
Decorator包装类的实例并提供与该实例相同的API。任何调用都被委托给包装的实例,并在需要时修改结果。
class Decorator
{
// …
public function __construct($decoratedInstance)
{
$this->_decoratedInstace = $decoratedInstance;
}
public function someMethod()
{
// call original method
$result = $this->_decoratedInstance->someMethod();
// decorate and return
return $result * 10;
}
// …
}
对于策略,请参阅Can I include code into a PHP class?
上的更完整示例可以在
找到更多详细信息和示例代码答案 2 :(得分:1)
我有几种方法供您尝试。 :)玩得开心。
class main_class {
private $_MODS = array(),...;
public ...;
public function __construct(...) {
...
global $MODS_ENABLED;
$this -> $_MODS = $MODS_ENABLED;
}
...
public function __get( $var ) {
foreach ( $this->_MODS as $mod )
if ( property_exists( $mod, $var ) )
return $mod -> $var;
}
public function __call( $method, $args ) {
foreach ( $this->_MODS as $mod )
if ( method_exists( $mod, $method ) )
return call_user_method_array( $method, $mod, $args );
}
}
class modMe {
private $_MODS = array();
public function __construct__() {
global $MODS_ENABLED;
$this -> $_MODS = $MODS_ENABLED;
}
public function __get( $var ) {
foreach ( $this->_MODS as $mod )
if ( property_exists( $mod, $var ) )
return $mod -> $var;
}
public function __call( $method, $args ) {
foreach ( $this->_MODS as $mod )
if ( method_exists( $mod, $method ) )
return call_user_method_array( $method, $mod, $args );
}
}
class mainClass extends modMe {
function __construct(...){
$this -> __construct__();
}
}
$MODS_ENABLED = array();
$MODS_ENABLED[] = new mod_mail();
$myObj = new main_class(...);
$myObj -> mail("me@me.me","you@you.you","subject","message/body","Extra:Headers;More:Headers");
# Hey look, my mail class was just added into my main_class for later use.
我目前在我自己的CMS中使用第一种方法(我只有一个类,mods是例外),我是从头开始制作的(http://sitegen.com.au),它工作得很好,我的需要这个的原因是因为我需要在./mods-enabled / *创建函数和更改其他函数的工作方式中的所有mod之后生成我的main_class,我还将在这里再次使用两个解决方案两个mod都改变了一个函数而没有赢得第一个。我将插件拆分为两个,在每个站点上运行的mod,以及具有站点设置的插件,甚至可能都没有启用。
玩得开心。
答案 3 :(得分:0)
您可以扩展课程
class foo {
public function a() {
return 'b';
}
}
class woo extends foo {
public function newStuff() {
$var = $this->a();
echo $var;
}
}
通过从woo类扩展foo,foo中的功能可用,同时你也可以在woo中创建新方法。这是向类添加新功能的最简单方法。
答案 4 :(得分:0)
您可以使用PHP的magic functionality来为在编译时未定义的方法提供操作。
答案 5 :(得分:0)
实际上是可能的。例如:
<?php
class Test {
function set($set, $val) {
$this->$set = $val;
}
function get($get) {
return $this->$get;
}
}
$t = new Test();
$t->set('hello', 'world');
echo $t->get('hello');
exit;
?>
答案 6 :(得分:0)
如果它不够神奇,您可以使用动态对象。常见的想法是:https://github.com/ptrofimov/jslikeobject