我正在为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解析器完成了他的工作):
#Logger.php (its definitely NOT a final version) -- generated by the XML parser
class Logger {
public function __call($name,$args) {
$log_level = args[0];
$args = array_slice($args,1);
switch($method_name) {
case 'foo':
case 'far':
//case .....
//write in log files
break;
}
//THEN, RELAY THE CALL TO THE INITIAL METHOD
}
}
#"dynamic" A.php
class A extends Logger {
public function foo($log_level, $bar) {
parent::foo($log_level, $bar);
echo ' // Hello there !';
}
public function bar($foo) {
echo " $ù$ùmezf$z !";
}
}
#"dynamic" B.php
class B extends Logger {
public function far($log_level, $boo) {
parent::far($log_level, $bar);
echo $boo;
}
}这里最大的挑战是,一旦XML解析器完成了它的工作,就将A和B转换成它们的“动态”版本。
理想的做法是在不修改A和B的代码(我指的是文件中的代码)的情况下实现这一点--或者至少找到一种方法,在程序完成后返回到它们的原始版本。
为了明确起见,我想找到在PHP中拦截方法调用的最合适的方法。
你对此有什么看法?
PS:当然,客户端代码不应该有任何后果(如果启用或不启用拦截,也没有什么不同)。
发布于 2010-04-22 20:13:01
您可以使用eval()来实际定义类,但是应该非常小心。eval()函数可能非常危险。
就像这样:
$parentName = 'Bar';
eval('class Foo extends ' . $parentName . ' { }');http://php.net/eval
发布于 2010-05-02 13:55:28
这个解决方案再次使用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();*https://stackoverflow.com/questions/2694037
复制相似问题