1

我以前从未在我的代码中使用过 Try-catch,但现在我需要这样做,而且我似乎不太了解它的工作方式。我在使用explode的字符串中有数据:

$groupNumbers = array();
$str = $dataGroups['groups'];
$groupNumbers = explode(",", $str);
$count = count($groupNumbers);

然后我想检查每个元素是否都是数字的,如果是我继续进行数据库查询,否则我想中止操作 ant 返回一些错误。

这是我正在做的事情:

for ($i = 0; $i < $count; ++$i)
    {
        try
        {
            is_numeric($groupNumbers[$i]);

        }
        catch (Exception $ex)
        {
            process_exception_to_json($ex);
        }
    }

如果 evrery 元素是数字,我会构造一条活动记录来执行 SQL:

$this->db->insert_batch('users_groups', $datas);

显然是这样写的,即使一个元素不是数字的,动作也不会中止,并且 insert_batch 仍然使用无效值执行,这是我想要避免的。这样做的确切方法是什么,所以我可以得到一个异常,同时中止操作。谢谢

勒隆

4

4 回答 4

2

这是因为is_numericDocs不会抛出异常而是返回一个值。它永远不会失败/抛出异常。

你需要这样做(只是一个例子,我不建议这样做,因为它是多余的):

try
{
    if (!is_numeric($groupNumbers[$i])) {
        throw new RuntimeException('Not numeric.');
    }

}
catch (Exception $ex)
{
    process_exception_to_json($ex);
}

而是创建您自己的组号类型:

try
{
    $groupNumbers = GroupNumbers::createFromString($dataGroups['groups']);
}
catch (Exception $ex)
{
    process_exception_to_json($ex);
}

使用以下类型:

class GroupNumbers extends ArrayObject
{
    public function construct(Array $numbers) {
        foreach ($numbers as $number)
        {
            if (!is_numeric($number))
            {
                throw new InvalidArgumentException(sprintf('Not numeric "%s".', $number));
            }
        }
        parent::__construct($numbers);
    }
    public static function createFromString($string) {
        return new self(explode(",", $string));
    }
}

现在封装了字符串处理,不再有外循环,GroupNumbers并且仅在字符串中有实际数字时才实例化。

如果你不熟悉类,你也可以通过程序风格获得类似的好处。它可能更容易理解(但几乎相同):

try
{
    $groupNumbers = GroupNumbers_createFromString($dataGroups['groups']);
}
catch (Exception $ex)
{
    process_exception_to_json($ex);
}

function GroupNumbers_createFromString($string)
{
    $numbers = explode(",", $string);
    foreach ($numbers as $number)
    {
        if (!is_numeric($number))
        {
            throw new InvalidArgumentException(sprintf('Not numeric "%s".', $number));
        }
    }
    return $numbers;
}
于 2012-04-04T08:38:40.470 回答
1

如果你想验证,你不需要Exception在这里使用

for ($i = 0; $i < $count; ++$i)
{
    if((int) $groupNumbers[$i] <= 0) {
        process_exception_to_json($groupNumbers[$i]);
        break; //optinal
    }
}
于 2012-04-04T08:43:05.053 回答
1

is_numeric从不抛出任何异常,因此您的示例不执行任何操作,这将起作用:

for ($i = 0; $i < $count; ++$i)
{
    try
    {
        if (is_numeric($groupNumbers[$i]) !== true)
        {
            throw new Exception($groupNumbers[$i] . ' is not numeric');
        }
    }

    catch (Exception $ex)
    {
        process_exception_to_json($ex);
    }
}

以下将完成(几乎)相同的事情:

for ($i = 0; $i < $count; ++$i)
{
    if (is_numeric($groupNumbers[$i]) !== true)
    {
        process_exception_to_json($groupNumbers[$i] . ' is not numeric');
    }
}
于 2012-04-04T08:39:32.887 回答
0

您需要做一些实际上在 try 块中引发异常的事情。is_numeric() 只会返回 false,所以这不起作用。这将:

try {
    if (!is_numeric($groupNumbers[$i]) {
        throw new exception('Uh-oh!');
    } 
} catch (Exception $ex) {
    process_exception_to_json($ex);
}

最好这样做:

function checkNumbers($groupNumbers) {
    for ($i = 0; $i < count($groupNumbers); ++$i) {
        if (!is_numeric($groupNumbers[$i]) {
            throw new Exception('"'.$groupNumbers[$i]." is non-numeric!");
        } 
    }
}

try {
    checkNumbers($numbers);
    // Won't get this far if it throws an exception
    $this->db->insert_batch('users_groups', $numbers);
} catch (Exception $ex) {
    process_exception_to_json($ex);
}

异常可以非常深入地嵌套在代码中,主要好处是错误消息是特定的,并且会冒泡,而您不必担心大量的真值或假值。您可能从 checkNumbers() 调用了数十个链式函数,无论出现什么错误,它都会在 catch 块中弹出,准备好将其发送到 JSON。

于 2012-04-04T08:50:34.147 回答