可靠的整数类型转换
我正在为 PHP 开发一个数据验证器包(主要是作为 5.3 中一些新添加的练习,例如命名空间)。我计划有一个主验证器类,它使用插件类来进行实际验证。
我正在构建的第一个验证插件只是一个简单的整数验证插件。来源如下:
namespace validator\validatorplugins;
class Integer implements ValidatorPlugin
{
private
$field = NULL;
public function cast ()
{
return ($this -> field = (int) ($this -> field * 1));
}
public function isValid ()
{
if (!$isValid = is_int ($this -> field * 1))
{
$this -> field = NULL;
}
return ($isValid);
}
public function __construct ($field)
{
$this -> field = $field;
}
public function __toString()
{
return ((string) $this -> field);
}
}
我正在使用上述类的以下测试:
$a = new Integer (0xDEADBEEF);
var_dump ($a -> isValid ());
var_dump ($a -> cast ());
echo ($a . "\n\n");
$b = new Integer ('0xDEADBEEF');
var_dump ($b -> isValid ());
var_dump ($b -> cast ());
echo ($b . "\n\n");
$c = new Integer (0777);
var_dump ($c -> isValid ());
var_dump ($c -> cast ());
echo ($c . "\n\n");
$d = new Integer ('0777');
var_dump ($d -> isValid ());
var_dump ($d -> cast ());
echo ($d . "\n\n");
从上面的测试用例中我得到以下结果:
布尔(true)int(3735928559)3735928559
布尔(true)int(3735928559)3735928559
布尔(true)int(511)511
布尔(true)int(777)777
如您所见,我遇到了一个问题编码八进制数的字符串。它的计算结果应该是 511(以 10 为基数的 0777),但实际上我得到的是 777。
因为有一天我可能想要使用此类来验证表单,并且由于 PHP 始终将表单视为字符串数组,因此您可以看到使用此插件处理恰好是字符串的八进制数字是有问题的。
我尝试了各种整数验证方法(使用 is_int 对于字符串总是返回 false,乘以 1 并且 is_numeric 不会捕获浮点数,类型转换和 intval 在处理八进制数时会产生不需要的结果)。我是否可以使用其他一些适用于基数 10(十进制)、基数 16(十六进制)和基数 8(八进制)的方法?
I'm working on a data validator package for PHP (mostly as an exercise in some of the new additions in 5.3 such as namespaces). I'm planning to have a main validator class which uses plugin classes to do the actual validation.
The first validation plugin I'm building is just a simple one for integers. The source is below:
namespace validator\validatorplugins;
class Integer implements ValidatorPlugin
{
private
$field = NULL;
public function cast ()
{
return ($this -> field = (int) ($this -> field * 1));
}
public function isValid ()
{
if (!$isValid = is_int ($this -> field * 1))
{
$this -> field = NULL;
}
return ($isValid);
}
public function __construct ($field)
{
$this -> field = $field;
}
public function __toString()
{
return ((string) $this -> field);
}
}
I'm using the following tests of the above class:
$a = new Integer (0xDEADBEEF);
var_dump ($a -> isValid ());
var_dump ($a -> cast ());
echo ($a . "\n\n");
$b = new Integer ('0xDEADBEEF');
var_dump ($b -> isValid ());
var_dump ($b -> cast ());
echo ($b . "\n\n");
$c = new Integer (0777);
var_dump ($c -> isValid ());
var_dump ($c -> cast ());
echo ($c . "\n\n");
$d = new Integer ('0777');
var_dump ($d -> isValid ());
var_dump ($d -> cast ());
echo ($d . "\n\n");
From the above test cases I'm getting the following results:
bool(true) int(3735928559) 3735928559
bool(true) int(3735928559) 3735928559
bool(true) int(511) 511
bool(true) int(777) 777
As you can see, I've run into an issue with a string that encodes an octal number. It should evaluate to 511 (0777 in base 10), but I'm actually getting 777 instead.
As I might one day want to use this class to validate forms, and as forms are always treated as arrays of strings by PHP, you can see that processing octal numbers that happen to be strings with this plugin is problematic.
I've tried various approaches to integer validation (using is_int always returns false for strings, multiplying by 1 and is_numeric will not catch floats, typecasting and intval produce an unwanted result when dealing with octal numbers). Is there some other approach I could use that would work for base 10 (decimal), base 16 (hex) and base 8 (octal)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
intval
有一个可选参数$base
:所以你可以这样做:
intval
has an optional argument$base
:So you could do something like this:
您首先需要定义如何在字符串中表示八进制数。因为有些人倾向于说像
"0777"
这样的字符串是777
十进制值。那么,您的类应该如何知道用户在执行您想要验证的输入时的想法(或更正确地转换为整数值)。
至于您想要模仿 PHP 本身如何“作为 PHP”解析值,您可以使用 eval 进行模拟(演示):
然而,这并没有解决根本的设计问题。您的沙箱类阵容应该有一个
DecimalInteger
或HexadecimalInteger
或OctalInteger
。You first need to define how an octal number is represented in a string. Because some folks tend to say that a string like
"0777"
is the777
decimal value.So how should your class know what the user thought when doing the input you would like to validate (or more correctly convert into an integer value).
As far as you're concerned to mimic how PHP itself resolves the value "as PHP", you can simulate with eval (Demo):
However this does not solve the underlying design problem. You should have a
DecimalInteger
or aHexadecimalInteger
orOctalInteger
for your line-up of your sandbox classes.