Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/230.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP运行时类修改_Php_Oop_Reflection_Class_Dynamic - Fatal编程技术网

PHP运行时类修改

PHP运行时类修改,php,oop,reflection,class,dynamic,Php,Oop,Reflection,Class,Dynamic,因此,我希望能够在运行时添加/删除类方法。在你告诉我这在oop中是可怕的做法之前,也许是,但我真的不在乎。我之所以希望能够做到这一点,是因为我希望应用程序是非常模块化的,因此一些插件可以扩展一些基类并向其中添加方法,而不会杀死主应用程序 例如,假设我有以下课程: class User { protected $Id; protected $Name; protected $Password; protected $PostsPerPage; } 比如说,一些插

因此,我希望能够在运行时添加/删除类方法。在你告诉我这在oop中是可怕的做法之前,也许是,但我真的不在乎。我之所以希望能够做到这一点,是因为我希望应用程序是非常模块化的,因此一些插件可以扩展一些基类并向其中添加方法,而不会杀死主应用程序

例如,假设我有以下课程:

class User {
    protected $Id;
    protected $Name;
    protected $Password;
    protected $PostsPerPage;
 }
比如说,一些插件增加了用户更改可见性设置的可能性,向类中添加了$Visible属性。课程将变成:

class User {
    protected $Id;
    protected $Name;
    protected $Password;
    protected $PostsPerPage;
    protected $Visible;
 }
这可以通过uuu get和uu set来实现,但最常见的实现是获取和设置运行时生成的属性,为每个添加的属性编写伪getter和setter会很麻烦,而且在我看来,使用u set是不可能的

我的另一个想法是将用户设置单独存储在另一个数组中,如$UserVisiblitySettings[userid],但这并不像我希望的那样是面向对象的

下一个想法是创建一个helper类,如下所示:

class UserHelper {
    public function SetVisiblity($user_object,value);
}
然后,我可以使用uuuu get和uuu set来实现“friend”方法/类,但这听起来太粗糙了。如果我走那条路的话,还不如打个超负荷的电话,接个电话就可以了。我也不太确定这是不是一个好的OOP实践,它看起来也很难看

我的最后一个想法是使用eval()在运行时使用一些函数动态创建类(这也是我能想到的eval的唯一有效用法)。基本上,从文件中获取类定义,进行一些简单的括号查找,找到类的开始括号和结束括号,并将其发送给eval

使用runkit是不可能的,因为它已经过时了,我不想强迫用户安装一些扩展

当我回顾我的想法时,最简单、cpu占用较少的方法似乎是重载调用,并添加一种在类中注册方法的方法


请注意,任何不是“不要这样做”的想法都将受到赞赏。

PHP不允许这样做。在其他方面,它可能是一种动态语言,但类系统是故意限制的。您可以安装扩展,该扩展更改了语言以允许在运行时对类进行模拟(但是您不再使用普通PHP),也可以使用来模拟它。

扩展可以做到这一点(
runkit\u method\u add()
,等等)

然而,这是一个实验性的扩展,你已经瞄准了你的脚

您还有其他选择:

  • 使用
    \uu get()
    \uu call()
  • 使用子类化和工厂模式(
    classpluginextensedbaseimplementation
    并让工厂实例化
    Plugin
    ,而不是
    BaseImplementation
    )。Zend Plugin Loader可以执行类似的操作。
    它是开销最小的解决方案,但也仅限于扩展一个类的一个插件
  • 添加挂钩并使用委派(策略模式)(
    $this->plugin->onFoo()

      您可以重写该类,但我不知道您是否可以在同一请求中重新加载它。 使用中介器设计模式(symfony event dispatcher)可以实现一些行为更改,但您需要提前知道扩展点,并在将来触发扩展类将捕获的事件/消息

      如果可以等待下一个请求,请清除缓存(如果有的话)。我做了一个可能对你有帮助的工具。

      这里也有类似问题的更多答案,我在这里放了一些代码示例。

      本质上,您正在寻找ruby的extend/include机制()或(某种程度上)C#的扩展方法()的对应物?与C#的扩展方法一模一样。我相信工厂方法有一些限制,我现在记不起来了。我会尝试任何一种方法。工厂解决方案仅限于扩展一个类的一个插件。如果您需要任意数量的插件,请使用stickleback之类的方法。使用_调用结合定位器模式,我发现在这种情况下非常有用。这里有一个例子:。