我希望能够在特定函数前后注入一些php代码(探查器代码)。函数和文件将手动插入表单中,但我希望注入和删除是自动的。我使用一个正则表达式来定位所需的函数调用,但我找不到如何将启用代码放在前面,将禁用代码放在后面
我希望能够在特定函数前后注入一些php代码(探查器代码)。函数和文件将手动插入表单中,但我希望注入和删除是自动的。我使用一个正则表达式来定位所需的函数调用,但我找不到如何将启用代码放在前面,将禁用代码放在后面
我想,错误的问题会得到错误的答案。如果您想评测特定的函数,请使用像XDebug这样的评测器,而不是您自己编写的评测器。代码注入来执行评测听起来工作量很大,尽管使用runkit是可能的,正如Vyktor所建议的那样。
如果你真的想运行自己的代码,我想最简单的解决方案是这样做:
<?php
$profiler = function( $function ) {
// your profiling code here.
};
$profiler( 'yourfunction' );
yourfunction( );
$profiler( 'yourfunction' );
然后,当您完成对应用程序的分析时,您可以简单地为$profiler
使用一个不起任何作用的替代函数,这意味着它不会具有侵入性。
$profiler = function( $function ) {
return;
};
尽管如此,这还是会让评测遍布整个应用程序。我只会使用现有的工具。
函数-runkit
您可以使用php runkit来简单地重写该函数。假设您想要替换函数foo()
,首先您需要用runkit_function_rename()
:重命名该函数
runkit_function_rename( 'foo', '_foo');
而不仅仅是简单地重新定义您的函数(通过func_get_args()
和call_user_func_array()
动态处理参数):
function foo() {
// Pre code
$result = call_user_func_array( '_foo', func_get_args());
// Post code
return $result;
}
完成后,您可以删除临时功能runkit_function_remove()
:
runkit_function_remove( 'foo');
// And set up old one back
runkit_function_rename( '_foo', 'foo');
如果你真的需要更改函数的代码(内联),那么"预回调"answers"后回调"是不够的,恐怕我有关于你的应用程序设计的坏消息。
方法-简单包装
当你需要更新方法(而不是函数)时,你可以利用php魔术方法用简单的包装器封装整个对象,你可能应该实现所有这些方法,但我只展示__call()
、__set()
、__get()
和__isset()
。
class Wrapper {
// The class that we are about to handle
protected $___data = null;
// Actually the only function that is directly related to Wrapper class
public function __construct( $data){
$this->___data = $data;
}
// By default just call real method
// You may add pre and post callbacks for every function
public function __call( $funcName, $args){
return call_user_func_array( array( $this->___data, $funcName), $args);
}
// Propagate set to deeper level
public function __set( $key, $val){
$result = ($this->___data->{$key} = $val);
if( $result == $this->___data){
return $this;
}
return $result;
}
// Propagate get to deeper level
public function __get( $key){
$result = $this->___data->{$key};
if( $result == $this->___data){
return $this;
}
return $result;
}
// Handles isset
public function __isset( $key){
return isset( $this->___data->{$key});
}
}
一旦你有了这个,你可以简单地扩展这个类,只对一个方法有特殊的处理(比如类Bar
方法foo()
):
WrapperBar extends Wrapper {
public function foo(){
// Add magick
return call_user_func_array( array( $this->___data, 'foo'), func_get_args());
}
}
并将其用作:
$bar = new Bar();
$bar = new WrapperBar( $bar);
$bar->foo( 'One', 'Two', '...');