开发者

Reliable integer typecasting

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)?


intval has an optional argument $base:

intval('0777', 8); // 511
intval('0777', 10); // 777
intval('0777'); // 777
intval(0777); // 511

So you could do something like this:

$i = '0777';

$base = 10;
if (strtolower(substr($i, 0, 2)) === '0x') $base = 16;
else if (substr($i, 0, 1) === '0') $base = 8;

intval($i, $base);


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 the 777 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):

<?php

$value = '0777';

$value = eval("return $value;");

var_dump($value);

However this does not solve the underlying design problem. You should have a DecimalInteger or a HexadecimalInteger or OctalInteger for your line-up of your sandbox classes.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜