Php 是否可以动态地向类添加代码/扩展类?
我想为我的代码编写一种“插件/模块”系统,如果我能在定义了类之后将其“添加”到类中,这会变得更容易 例如,类似这样的内容:Php 是否可以动态地向类添加代码/扩展类?,php,Php,我想为我的代码编写一种“插件/模块”系统,如果我能在定义了类之后将其“添加”到类中,这会变得更容易 例如,类似这样的内容: class foo { public function a() { return 'b'; } } 这是我的班级。现在,我想在它定义之后,向它添加另一个函数/变量/常量 我意识到这可能是不可能的,但我需要确认。您可以扩展该类 class foo { public function a() { return 'b'; } } class
class foo {
public function a() {
return 'b';
}
}
这是我的班级。现在,我想在它定义之后,向它添加另一个函数/变量/常量
我意识到这可能是不可能的,但我需要确认。您可以扩展该类
class foo {
public function a() {
return 'b';
}
}
class woo extends foo {
public function newStuff() {
$var = $this->a();
echo $var;
}
}
通过从woo类扩展foo,foo中的功能可用,同时您还可以在woo中创建新方法。这是向类添加新功能的最简单方法。您可以使用PHP在编译时未定义的方法上提供操作。这实际上是可能的。例如:
<?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;
?>
否,您不能在运行时将方法添加到已定义的类中 但是您可以使用
\uuuu call/\uuuu 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";
这个解决方案非常有限,但可能对您有用。要添加/更改类在运行时的行为,您应该使用装饰器和/或策略。这是首选的OO方法,而不是求助于任何神奇的方法或猴子补丁 装饰器包装类的实例,并提供与该实例相同的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;
}
// …
}
有关策略,请参阅我在
有关更多详细信息和示例代码,请访问
- 我有一些方法供您尝试。:)享受编码的乐趣
仅用于一个类的方法:
要处理多个类时的方法:
现在让我们尝试使用它们:
注:
我目前正在我自己的CMS中使用第一种方法(我只有一个类,mods是例外),这是我从头开始制作的(http://sitegen.com.au),而且效果很好,我之所以需要这样做,是因为我需要在./mods enabled/*中创建所有mod并更改其他函数的工作方式后,生成了我的主_类。我还将再次回到这里,提供一个解决方案,两个mod都可以更改一个函数,但没有一个mod在第一次运行时获胜。我将插件分为两部分,一部分是在每个站点上运行的MOD,另一部分是为某个站点设置的插件,甚至可能无法启用。
享受编程乐趣。如果对你来说还不够神奇,你可以使用动态对象。这里有一个共同的想法:你能告诉我你所说的定义是什么吗?你的意思是文件已经包括在内,但没有对象被初始化,还是有对象被初始化?我想我在irc.freenode.net上见过你,你注册了吗?还是有人偷了你的freenode在线别名?@JamesM SiteGen是的。那应该是我。你好,你喜欢我的答案吗?小而简单。:)看到了,很好的解决方案/讨论指向,但是我必须在我的课堂上使用woo类,而不是foo,对吗?你必须通过woo而不是foo来使用你添加的功能。基本上,您可以保持foo类不变,但可以通过从不同的其他类扩展它来添加不同的功能。如果你不知道你想让你的代码做什么,就很难给出对你有用的确切例子。我想更多地添加函数和常量之类的东西。我应该在我的作品中这样说…这在什么方面是有限的?我能看到这种限制的唯一方式可能是无法添加受保护的方法。
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.