PHP是否可以编写其他PHP函数,如Lisp宏?

时间:2012-01-06 18:28:17

标签: php macros

我正在编写一个单元测试平台,我希望能够根据我正在测试的Web服务中的每个函数动态生成一个函数。动态函数将使用Web服务中每个参数的默认(正确)值生成,并允许使用错误测试的错误值轻松交换它们。

$arrayOfDefVals = array(123, 'foo');

testFunctionGenerator('function1', $arrayOfDefVals);

//resulting php code:
function1Test($expectedOutput, $arg1=123, $arg2='foo')
{
    try
    {
        $out = function1($arg1, $arg2);
        if($expectedOutput === $out)
            return true;
        else
            return $out;
    } 
    catch ($e) 
    {
        return $e;
    } 
}

这将允许我一次快速,干净地传递一个错误的参数或任意数量的错误参数,以测试Web服务中捕获的所有错误。

我的主要问题是: 这甚至可以与PHP? 如果不可能,还有替代方案吗?

编辑:我不是在寻找单元测试,我正在努力学习。我不是在寻找有关此代码示例的建议,它只是我想要做的一个简单示例。我只是想知道它是否可能。

4 个答案:

答案 0 :(得分:2)

嗯,对于初学者,您可以在函数中设置默认参数:

function function1Test($expectedOutput, $testArg1=123, $testArg2='foo') {
   ...
}

除此之外,我不确定你用这个“函数发生器”想要实现的目标......

答案 1 :(得分:2)

我不会先尝试,因为PHP没有内置宏支持。但可能是朝这个方向发展的事情:

function function1($param1, $param2)
{
    return  sprintf("param1: %d, param2: '%s'\n", $param1, $param2);
}

/* Macro: basically a port of your macro as a function */

$testFunctionGenerator = function($callback, array $defVals = array())
{
    $defVals = array_values($defVals); // list, not hash
    return function() use ($callback, $defVals)
    {
        $callArgs = func_get_args();
        $expectedOutput = array_shift($callArgs);

        $callArgs += $defVals;

        return $expectedOutput == call_user_func_array($callback, $callArgs);
    };
};

/* Use */

$arrayOfDefVals = array(123, 'foo');

$function1Test = $testFunctionGenerator('function1', $arrayOfDefVals);

var_dump($function1Test("param1: 456, param2: 'foo'\n", 456)); # bool(true)

这可能会有所帮助,请参阅Anonymous functions­Docsfunc_get_args­DocsUnion array operator­Docscall_user_func_array­Docs

答案 2 :(得分:0)

了解call_user_funcfunc_get_args

手册中的这个例子可以帮助您走上正确的道路:

<?php
call_user_func(function($arg) { print "[$arg]\n"; }, 'test'); /* As of PHP 5.3.0 */
?>

答案 3 :(得分:0)

如果它是一个你有文件访问权限的函数(即,它不是PHP标准库的一部分,你有权从文件中读取),你可以这样做:

假设我们在某个文件中有这样的函数。必须包含该文件(即,该函数必须在PHP的内部符号表中):

function my_original_function($param1, $param2)
{
    echo "$param1 $param2 \n";
}

使用ReflectionFunction类获取有关该函数及其定义位置的详细信息:http://us2.php.net/manual/en/class.reflectionfunction.php

$ reflection = new ReflectionFunction('my_original_function');

接下来,您可以使用反射实例来获取该文件的路径,函数的第一个/最后一个行号以及函数的参数:

$file_path = $reflection->getFileName();
$start_line = $reflection->getStartLine();
$end_line = $reflection->getEndLine();
$params = $reflection->getParameters();

使用这些,你可以:

  1. 将文件中的函数读入字符串
  2. 使用已知函数名称作为参考重写第一行以更改函数名称
  3. 使用$ params作为参考重写第一行以更改参数默认值
  4. 将更改的函数字符串写入文件
  5. 包含文件
  6. 瞧!您现在可以使用新功能。
  7. 根据实际实际尝试完成的内容,您还可以使用ReflectionFunction :: getClosure()来获取函数的闭包副本,将其分配给您的任何变量想要,并在那里定义参数。见:http://us.php.net/manual/en/functions.anonymous.php。或者您可以实例化多个ReflectionFunction并使用您想要的参数集调用ReflectionFunction :: invoke()/ invokeArgs()。请参阅:http://us2.php.net/manual/en/reflectionfunction.invokeargs.phphttp://us2.php.net/manual/en/reflectionfunction.invoke.php