gpt4 book ai didi

PHP 类型转换 - 好还是坏?

转载 作者:行者123 更新时间:2023-12-02 02:50:06 25 4
gpt4 key购买 nike

在使用 C 和 Java 进行了一些工作之后,我对 PHP 中的狂野西部法律越来越恼火。我真正觉得 PHP 缺乏的是严格的数据类型。 string('0') == (int)0 == (boolean)false 就是一个例子。

您不能依赖于函数返回的数据类型。您既不能强制函数的参数为​​特定类型,这可能会导致非严格比较,从而导致意外情况。一切都可以解决,但它仍然容易出现意外错误。

对方法接收到的参数进行类型转换是好还是坏的做法?对返回进行类型转换是否好?

浏览器

public function doo($foo, $bar) {
$foo = (int)$foo;
$bar = (float)$bar;
$result = $bar + $foo;
return (array)$result;
}

这个例子很愚蠢,我还没有测试过,但我认为每个人都明白。 PHP大神除了让不知道数据类型的人使用PHP之外,还有什么理由可以随意转换数据类型吗?

最佳答案

无论好坏,松散类型是 “PHP 方式” .许多内置函数和大多数语言结构将在您提供给它们的任何类型上运行——默默地(通常是危险地)将它们转换到幕后以使事物(某种程度上)组合在一起。

我本人来自 Java/C/C++ 背景,PHP 的松散类型模型一直让我感到沮丧。但多年来我发现,如果我必须编写 PHP,我可以通过拥抱 PHP 的“松散性”而不是与之抗争来做得更好(即更干净、更安全、更可测试的代码);因为它,我最终变成了一只更快乐的猴子。

强制转换确实是我的技术的基础——而且(恕我直言)这是始终构建干净、可读的 PHP 代码的唯一方法,该代码以易于理解、可测试、确定性的方式处理混合类型参数。

要点(您也清楚地了解)是,在 PHP 中,您不能简单地假设参数是您期望的类型。这样做可能会产生严重的后果,在您的应用程序投入生产之前您不太可能发现这些后果。

为了说明这一点:

<?php

function displayRoomCount( $numBoys, $numGirls ) {
// we'll assume both args are int

// check boundary conditions
if( ($numBoys < 0) || ($numGirls < 0) ) throw new Exception('argument out of range');

// perform the specified logic
$total = $numBoys + $numGirls;
print( "{$total} people: {$numBoys} boys, and {$numGirls} girls \n" );
}

displayRoomCount(0, 0); // (ok) prints: "0 people: 0 boys, and 0 girls"

displayRoomCount(-10, 20); // (ok) throws an exception

displayRoomCount("asdf", 10); // (wrong!) prints: "10 people: asdf boys, and 10 girls"

解决这个问题的一种方法是限制函数可以接受的类型,当检测到无效类型时抛出异常。其他人已经提到了这种方法。它非常符合我的 Java/C/C++ 美学,并且我多年来在 PHP 中遵循这种方法。简而言之,它没有任何问题,但它确实与“PHP 方式”背道而驰,过了一段时间,这开始让人感觉像逆流而上。

作为替代方案,强制转换提供了一种简单而干净的方法来确保函数对于所有可能的输入都具有确定性的行为,而无需编写特定的逻辑来处理每种不同的类型。

使用强制转换,我们的示例现在变为:
<?php

function displayRoomCount( $numBoys, $numGirls ) {
// we cast to ensure that we have the types we expect
$numBoys = (int)$numBoys;
$numGirls = (int)$numGirls;

// check boundary conditions
if( ($numBoys < 0) || ($numGirls < 0) ) throw new Exception('argument out of range');

// perform the specified logic
$total = $numBoys + $numGirls;
print( "{$total} people: {$numBoys} boys, and {$numGirls} girls \n" );
}

displayRoomCount("asdf", 10); // (ok now!) prints: "10 people: 0 boys, and 10 girls"

该函数现在按预期运行。事实上,很容易证明函数的行为现在已针对所有可能的输入进行了明确定义。这是因为强制转换操作对于所有可能的输入都是明确定义的;强制转换确保我们始终使用整数;并且函数的其余部分被编写为对所有可能的整数进行明确定义。

Rules for type-casting in PHP are documented here ,(请参阅页面中间的特定于类型的链接 - 例如:“转换为整数”)。

这种方法有一个额外的好处,即函数现在的行为方式与其他 PHP 内置函数和语言结构一致。例如:
// assume $db_row read from a database of some sort
displayRoomCount( $db_row['boys'], $db_row['girls'] );

尽管 $db_row['boys'] 会正常工作和 $db_row['girls']实际上是包含数值的字符串。这与普通 PHP 开发人员(不知道 C、C++ 或 Java)期望它工作的方式是一致的。

至于转换返回值:这样做没有什么意义,除非您知道您有一个潜在的混合类型变量,并且您希望始终确保返回值是特定类型。这种情况更常见于代码的中间点,而不是从函数返回的点。

一个实际例子:
<?php

function getParam( $name, $idx=0 ) {
$name = (string)$name;
$idx = (int)$idx;

if($name==='') return null;
if($idx<0) $idx=0;

// $_REQUEST[$name] could be null, or string, or array
// this depends on the web request that came in. Our use of
// the array cast here, lets us write generic logic to deal with them all
//
$param = (array)$_REQUEST[$name];

if( count($param) <= $idx) return null;
return $param[$idx];
}

// here, the cast is used to ensure that we always get a string
// even if "fullName" was missing from the request, the cast will convert
// the returned NULL value into an empty string.
$full_name = (string)getParam("fullName");

你明白了。

有几个问题需要注意
  • PHP 的转换机制不够智能,无法优化“无操作”转换。因此,强制转换总是会导致创建变量的副本。在大多数情况下,这不是问题,但如果您经常使用这种方法,则应将其牢记在心。因此,强制转换可能会导致引用和大型数组出现意外问题。见 PHP Bug Report #50894了解更多详情。
  • 在 php 中,一个太大(或太小)而无法表示为整数类型的整数将自动表示为浮点数(或 double 数,如有必要)。这意味着 ($big_int + $big_int) 的结果实际上可以是一个浮点数,如果将其转换为 int,则结果数字将是胡言乱语。因此,如果您正在构建需要对大整数进行运算的函数,您应该记住这一点,并可能考虑其他一些方法。


  • 很抱歉这篇长文章,但这是我深入考虑过的一个话题,多年来,我已经积累了很多关于它的知识(和意见)。把它放在这里,我希望有人会发现它有帮助。

    关于PHP 类型转换 - 好还是坏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3695295/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com