PHP函数参数类型最佳实践

3
我目前正在开发一个框架,遇到了问题......当有人调用框架中的函数时,如何处理参数类型不正确的情况?
例如:
// Title is expected to be string, comment_num is expected to be int
function example1($title, $comment_num) {


 // Doesnt throw error, just converts type 
 $title = (string) $title;
 $comment_num = (int) $comment_num;

}

或者

// Title is expected to be string, comment_num is expected to be int

function example2($title, $comment_num) {


 if (!is_string($title)) {

  trigger_error('String expected for first parameter', E_USER_WARNING);
  return;
 }

 if (!is_string($title)) {

  trigger_error('Int expected for second parameter', E_USER_WARNING);
  return
 }
}

还是混合使用的方式比较好?抛出错误并强制转换类型?

最好的方法是什么?我计划发布它,所以不只是我会用它,因此我也要考虑到其他人。谢谢。

编辑!!!

所以我决定给出答案,但我也想发布我编写的代码,它可以让我快速检查类型。它有点粗糙,但足够好用了。

function __type_check($params) {

    if (count($params) < 1) {

        return; 
    }
    $types = func_get_args();
    array_shift($types);

    $backtrace = debug_backtrace();
    $backtrace = $backtrace[1];

    $global_types = array(
        'bool'  => 'boolean',
        'int'   => 'integer',
        'float' => 'double' 
    );

    $error = false;


    for ($i = 0, $j = count($types); $i < $j; ++$i) {

        if (strpos($types[$i], ',') === false) {

            $type = strtolower($types[$i]);

            if (isset($global_types[$type])) {

                $type = $global_types[$type];
            }

            if (gettype($params[$i]) != $type) {
                $error = true;
                break;
            }

        } else {

            $current_types = array_map('trim', explode(',', $types[$i]));

            foreach ($current_types as $type) {

                $type = strtolower($type);  

                if (isset($global_types[$type])) {

                    $type = $global_types[$type];
                }

                if (gettype($params[$i]) == $type) {

                    continue 2; 
                }
            }

            $error = true;
            break;
        }       
    }

    if ($error) {
        trigger_error($backtrace['function'] . '() expects parameter ' . ($i + 1) . ' to be ' . $types[$i] . ', ' . gettype($params[$i]) . ' given', E_USER_WARNING);
        return false;
    }

    return true;
}

你会像这样使用它:
function string_manipulation($str, $str2, $offset = 1) {

    if (!__type_check(func_get_args(), 'string', 'string', 'int,float')) {

        return false;   
    }   

    // do manipulation here
}

基本上会检查第一个和第二个参数是否为字符串,第三个参数是整数或浮点数。您可以组合任何类型的 'string、int、array、object' 等,所有有效类型都从 gettype 中获取。
/* 已知的错误 */ null 是一种类型,无法确定它是否应该是这样 如果输入类名,则不会检查实例,而只会执行类型检查 还没有找到触发错误的好方法...... 嗯
这就是我要说的了,这些错误很容易修复 :D

3
我的建议是:不要使用trigger_error,而应该抛出异常(throw exceptions)。它们更加灵活且更易有效地处理。 - ircmaxell
一个像数据类型这样微不足道的异常似乎有些过分了...你不能真的期望人们在try/catch中运行每个函数。 - Ozzy
看看现有的库是如何做的。它们中的许多会返回错误,但有些还会抛出警告,这非常令人烦恼(fopen()是我最喜欢的例子)。我认为,如果你可以在不丢失信息的情况下转换参数,请这么做;如果不能,则返回一个错误代码。 - staticsan
@static 我发现警告对于调试来说非常有帮助。您能详细说明为什么您觉得它们很烦人吗? - deceze
1
考虑到我总是安装一个ErrorException错误处理程序,我根本不使用标准的错误报告系统。我受不了它(因为很难检测和捕获错误,所以你需要添加其他检查,如返回值)。至少使用异常需要你至少承认错误。警告和通知可以轻易地被忽略。至于它看起来有点多,SPL中定义了一个InvalidArgumentException的原因。解决问题的不同方法,但我个人认为trigger_error是一种不好的做法... - ircmaxell
显示剩余5条评论
3个回答

6

这要看情况而定。

PHP是一种动态类型语言,有时候这样做是有好处的。由于它处理大量HTTP数据,这些数据都是字符串类型,因此数字并不总是int类型,但对于一般操作仍然可以正常工作。

严格执行基本类型通常与PHP的风格不符,并可能很麻烦。

在PHP中通常的做法是接受几乎任何类型的参数,并在信任的基础上使用它们,直到您需要具体结果或类型成为一个问题。

function example1($title, $comment_num) {

    // do some operations that should work error-free regardless of type

    if ($result != 'something specific you expect here') {
        throw new Exception('Something went wrong!');
        // or
        trigger_error('Something went wrong!');
        return false;
    }

    // continue with $result
}

您可以选择面向对象编程(OOP)的方式来构建对象。对象在某种程度上具有灵活性,可以接受一定范围内的内容。如果成功构建对象,您将获得一个特定类型的已定义对象,可用于PHP的强制类型提示:

function example1(TitleObject $title) {
    // rest assured that $title is of the right type
}

这也是我会采取的方法。面向对象编程路线加一! - Josh

0

如果可以的话,只需使用SPLTypes并完成;否则抛出InvalidArgument异常


0

我会自动转换 int 和 string 数据类型,而不会发出警告(因为它们很容易混淆),但对于像资源或对象这样的东西,通知程序员错误可能是一个有用的功能。

我还会将通知代码设置在它自己的函数中,这样事情就不会变得如此重复。无论如何,祝你好运!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接