Nic*_*ars 8 php function type-hinting
我已经构建了一系列字符串函数,它们可以执行各种操作,我注意到我实际上没有任何内部函数检查,以确保变量是一个字符串,然后才能完成它.
因此,在开发过程中的几次,我偶然传递了一些字符串以外的其他内容,从而导致错误.
现在,我想知道这是否是我应该一直这样做的事情.首先检查以确保已发送正确类型的数据/检查可能首先出现问题的事情,以某种方式记录它们,然后如果一切正常,请使用它做一些事情.
这是我应该坚持的吗?
您可以看到这是一个有些争议的话题。这是我的看法:
类型提示
尽可能使用类型提示。PHP 中的基本类型不可能有类型提示,所以,是的,您应该检查以确保收到有效的参数。如果没有,您的函数可能会抛出异常或返回一些默认值,例如 null 或 false。
防御性编程
编写可测试代码的想法是失败不是无声无息或神秘的。没有理由避免显式参数验证:越详细,您的代码就越清晰和可用。
除了验证参数之外,您还可以实现错误处理程序来捕获边缘情况。但是您应该验证大多数参数,特别是如果它们对持久数据(例如您的数据库)有影响。
墨菲定律完全有效,因此您必须尽可能多地应对可预测的错误。无效参数是一个容易预测的错误——无法验证它是代码中的定时炸弹。is_string例如,打电话很容易并且可以分散炸弹。
拳击
另一个考虑因素是“装箱”变量。这会导致代码非常冗长,但它确实具有允许基元类型提示的优点。
我从未见过有人在他们的整个代码库中真正做到这一点,但它就在那里。有可用于原始类型的 SPL 类,因此您最终会像这样:
function stringThing (\SplString $myString) { ... }
stringThing(new \SplString('This is my string'));
Run Code Online (Sandbox Code Playgroud)
SplTypes 强制执行原始类型并在误用时引发异常。从文档中:
$string = new SplString("Testing");
try {
$string = array(); // <----------this will throw an exception
} catch (UnexpectedValueException $uve) {
echo $uve->getMessage() . PHP_EOL;
}
Run Code Online (Sandbox Code Playgroud)
SplTypes 是一个 PECL 扩展,并不总是标准 PHP 安装的一部分,因此在使用它之前请检查您的扩展。该扩展也被认为是实验性的,尽管它已经存在了一段时间。
您还可以相当简单地创建自己的盒子:
class myStringBox {
private $string = '';
public function __construct($string=null) {
if ($string)
$this->set($string);
}
public function set($val) {
if (!is_string($string)) throw new \InvalidArgumentException();
$this->string= $val;
}
public function __toString() {
return $this->string;
}
public function trim() { return trim($this->string); } // extend with functions?
}
Run Code Online (Sandbox Code Playgroud)
...但这有一个主要的功能差异,因为您不能像这样直接设置新的字符串值:
$stringBox = new myStringBox('hello world! ');
echo $stringBox; // "hello world![space]"
echo $stringBox->trim(); // "hello world!"
$stringBox = 'A new string';
echo $stringBox->trim(); // Error: Call to a member function trim() on a non-object
Run Code Online (Sandbox Code Playgroud)
相反,您必须使用 setter 方法:
$stringBox = new myStringBox('hello world! ');
echo $stringBox; // "hello world![space]"
echo $stringBox->trim(); // "hello world!"
$stringBox->set('A new world');
echo $stringBox->trim(); // "A new world"
Run Code Online (Sandbox Code Playgroud)
这一切都让我们回到类型提示,这可能是不必验证参数的最有效方法。
相关阅读