PHP5中的方法拦截*

PHP5中的方法拦截*,php,interceptor,xml-parsing,Php,Interceptor,Xml Parsing,我正在为PHP实现一个日志系统,我有点卡住了 所有配置都在XML文件中定义,该文件声明要记录的每个方法。XML被很好地解析并转换为多维数组(classname=>array of methods)。到目前为止,一切顺利 让我们举一个简单的例子: #A.php class A { public function foo($bar) { echo ' // Hello there !'; } public function bar($foo) { echo

我正在为PHP实现一个日志系统,我有点卡住了

所有配置都在XML文件中定义,该文件声明要记录的每个方法。XML被很好地解析并转换为多维数组(
classname=>array of methods
)。到目前为止,一切顺利

让我们举一个简单的例子:

#A.php
class A {
    public function foo($bar) {
        echo ' // Hello there !';
    }

public function bar($foo) {
    echo " $ù$ùmezf$z !";
}
}

#B.php
class B {
public function far($boo) {
    echo $boo;  
}
}
现在,假设我有这个配置文件:

<interceptor>
<methods class="__CLASS_DIR__A.php">
        <method name="foo">
    <log-level>INFO</log-level>
    <log-message>Transaction init</log-message>
        </method>
</methods>  
<methods class="__CLASS_DIR__B.php">
        <method name="far">
    <log-level>DEBUG</log-level>
    <log-message>Useless</log-message>
        </method>
</methods>
</interceptor>
这里最大的挑战是在XML解析器完成其工作后,将A和B转换为它们的“动态”版本

理想的做法是在根本不修改A和B的代码(我的意思是,在文件中)的情况下实现这一点,或者至少在程序完成后找到一种返回原始版本的方法

为了清楚起见,我想找到在PHP中拦截方法调用的最合适的方法

你对此有什么想法

PS:当然,对客户端代码应该没有影响(如果启用或未启用拦截,则没有区别)。

您可以使用
eval()
来实际定义类,但是您应该非常小心。
eval()
函数可能非常危险

大概是这样的:

$parentName = 'Bar';

eval('class Foo extends ' . $parentName . ' { }');

此解决方案再次使用eval,但我还是要发布它供您考虑,因为我认为这是一种非常好的动态继承方法

这里的方法是使用一个中间类,它扩展了一些可以更改的默认类(在本例中,扩展到另一个也扩展了默认类的类)

我不确定您的设置中有什么不允许这种工作——如果您澄清这一点,我可能会提供更好的建议

<?php

/*
 * One of the following classes will be the superclass of the Child
 */

class Ancestor {
    function speak() {
        echo 'Ancestor <br />';
    }
}

class Mum extends Ancestor {
    function speak() {
        parent::speak();
        echo 'Mum <br />';
    }
}

class Dad extends Ancestor {
    function speak() {
        parent::speak();
        echo 'Dad <br />';
    }
}

/*
 * Decide on which class we wish to make the superclass of our Child
 */

$parentClass = null;

if (isset($_GET['parent'])) {
    $parentClass = $_GET['parent'];
    if (!class_exists($parentClass)) {
        $parentClass = "Ancestor";
    }
}

if (!is_null($parentClass)) {
    eval("class ChildParent extends $parentClass {};");
} else {
    class ChildParent extends Ancestor {};
}

if (class_exists('ChildParent')) {
class Child extends ChildParent
{
    function speak() {
        parent::speak();
        echo 'Child <br />';
    }
}
}

/*
 * Show what's going on
 */

echo '<a href="?">Either</a> | <a href="?parent=Mum">Mum</a> | <a href="?parent=Dad">Dad</a> <br />';

$child = new Child();
$child->speak();*

我还不能完全理解你的处境。你能补充一些细节,或者展示一些相关的代码吗?这听起来似乎应该用另一种方法来完成。注:编辑并(希望如此)clarified@Rolf如果你的类已经是子类,你也会有问题吗?使用这种方法,您需要传播parent::调用链。+1,直到有人发布一种方法来定义一个新类而不使用eval()。请注意,runkit可以通过动态更改继承。不幸的是,runkit_class_Adoption是外部库的一部分,一旦应用程序被托管,它的使用就会受到影响。。。关于eval,我的类在运行时之前就已经定义好了,我希望避免在配置文件中的每个类主题中添加变量。。。看看最初的帖子,我用更好的方式解释了我的情况……我更新了最初的主题(及其标题)。你应该看一看,了解整个情况。多亏了您的示例,我想我理解了如何处理动态继承(一个默认超类和一个由XML解析器生成的超类)。它要么在类结构中,要么在对象本身的实例化中。第一种方法如上所述。第二种方法是
Neu::MyClass()而不是
新MyClass()。那是哪一个呢?
<?php

/*
 * One of the following classes will be the superclass of the Child
 */

class Ancestor {
    function speak() {
        echo 'Ancestor <br />';
    }
}

class Mum extends Ancestor {
    function speak() {
        parent::speak();
        echo 'Mum <br />';
    }
}

class Dad extends Ancestor {
    function speak() {
        parent::speak();
        echo 'Dad <br />';
    }
}

/*
 * Decide on which class we wish to make the superclass of our Child
 */

$parentClass = null;

if (isset($_GET['parent'])) {
    $parentClass = $_GET['parent'];
    if (!class_exists($parentClass)) {
        $parentClass = "Ancestor";
    }
}

if (!is_null($parentClass)) {
    eval("class ChildParent extends $parentClass {};");
} else {
    class ChildParent extends Ancestor {};
}

if (class_exists('ChildParent')) {
class Child extends ChildParent
{
    function speak() {
        parent::speak();
        echo 'Child <br />';
    }
}
}

/*
 * Show what's going on
 */

echo '<a href="?">Either</a> | <a href="?parent=Mum">Mum</a> | <a href="?parent=Dad">Dad</a> <br />';

$child = new Child();
$child->speak();*