【问题标题】:PHP function param type best practicesPHP 函数参数类型最佳实践
【发布时间】:2011-01-21 02:07:58
【问题描述】:

我目前正在开发一个框架,但遇到了一个障碍......当有人调用框架中的函数时,我应该如何处理不正确的参数类型?

例子:

// 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

【问题讨论】:

  • 我的建议:不要使用trigger_error。抛出异常。它们更灵活,更容易有效处理。
  • 一个像数据类型这样微不足道的东西的例外似乎有点多了..你不能真的期望人们在 try/catch 中运行每个函数
  • 这里没有回答你的问题,但如果你正在构建一个框架,你最好创建一个为你进行检查的函数,而你的其他函数/类引用那个函数.
  • 奥兹说了什么。由于 PHP 使用 E_WARNING 作为其内置函数,大多数程序员预计 E_WARNINGE_USER_WARNING 错误是由错误输入的参数引起的。 trigger_error() 在这里 IMO 可以。
  • 考虑到我总是安装一个 ErrorException 错误处理程序,我根本不使用标准的错误报告系统。我受不了(因为它是检测和捕获错误的皮塔,所以您需要添加其他检查,例如返回值)。至少对于 Exception 它要求您至少承认错误。警告和通知可以被忽略。就它的出现而言,SPL 中定义了一个InvalidArgumentException 是有原因的。解决问题的不同方法,但我个人认为trigger_error 是不好的做法......

标签: php frameworks


【解决方案1】:

视情况而定。

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
}

【讨论】:

  • 这也是我的处理方式。为 OOP 路线 +1!
【解决方案2】:

如果有的话,只需使用 SPLTypes 就可以了;否则抛出 InvalidArgument 异常

【讨论】:

    【解决方案3】:

    我会毫无怨言地自动对 int 和 string 数据类型进行类型转换(因为它们很容易混淆),但是对于资源或对象之类的东西,通知程序员错误可能是一个有用的功能。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-19
      • 1970-01-01
      • 2017-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多