PHP 类型转换 - 好还是坏? [英] PHP Typecasting - Good or bad?

查看:27
本文介绍了PHP 类型转换 - 好还是坏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

After some work in C and Java I've been more and more annoyed by the wild west laws in PHP. What I really feel that PHP lacks is strict data types. The fact that string('0') == (int)0 == (boolean)false is one example.

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

You cannot rely on what the data type a function returns is. You can neither force arguments of a function to be of a specific type, which might lead to a non strict compare resulting in something unexpected. Everything can be taken care of, but it still opens up for unexpected bugs.

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

Is it good or bad practice to typecast arguments received for a method? And is it good to typecast the return?

浏览器

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

这个例子很愚蠢,我还没有测试过,但我想每个人都明白.PHP大神除了让不懂数据类型的人用PHP,还有什么理由可以随意转换数据类型?

The example is quite stupid and I haven't tested it, but I think everyone gets the idea. Is there any reason for the PHP-god to convert data type as he wants, beside letting people that don't know of data types use PHP?

推荐答案

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

For better or worse, loose-typing is "The PHP Way". Many of the built-ins, and most of the language constructs, will operate on whatever types you give them -- silently (and often dangerously) casting them behind the scenes to make things (sort of) fit together.

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

Coming from a Java/C/C++ background myself, PHP's loose-typing model has always been a source of frustration for me. But through the years I've found that, if I have to write PHP I can do a better job of it (i.e. cleaner, safer, more testable code) by embracing PHP's "looseness", rather than fighting it; and I end up a happier monkey because of it.

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

Casting really is fundamental to my technique -- and (IMHO) it's the only way to consistently build clean, readable PHP code that handles mixed-type arguments in a well-understood, testable, deterministic way.

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

The main point (which you clearly understand as well) is that, in PHP, you can not simply assume that an argument is the type you expect it to be. Doing so, can have serious consequences that you are not likely to catch until after your app has gone to production.

为了说明这一点:

<?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 方式"背道而驰,过了一段时间,感觉就像逆流而上.

One approach to solving this is to restrict the types that the function can accept, throwing an exception when an invalid type is detected. Others have mentioned this approach already. It appeals well to my Java/C/C++ aesthetics, and I followed this approach in PHP for years and years. In short, there's nothing wrong with it, but it does go against "The PHP Way", and after a while, that starts to feel like swimming up-stream.

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

As an alternative, casting provides a simple and clean way to ensure that the function behaves deterministically for all possible inputs, without having to write specific logic to handle each different type.

使用强制转换,我们的例子现在变成:

Using casting, our example now becomes:

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

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

The function now behaves as expected. In fact, it's easy to show that the function's behavior is now well-defined for all possible inputs. This is because the the cast operation is well-defined for all possible inputs; the casts ensure that we're always working with integers; and the rest of the function is written so as to be well-defined for all possible integers.

此处记录了 PHP 中的类型转换规则,(请参阅页面中间特定类型的链接 - 例如:转换为整数").

Rules for type-casting in PHP are documented here, (see the type-specific links mid-way down the page - eg: "Converting to integer").

这种方法有一个额外的好处,即函数现在的行为方式与其他 PHP 内置函数和语言结构一致.例如:

This approach has the added benefit that the function will now behave in a way that is consistent with other PHP built-ins, and language constructs. For example:

// 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)所期望的工作方式一致.

will work just fine, despite the fact that $db_row['boys'] and $db_row['girls'] are actually strings that contain numeric values. This is consistent with the way that the average PHP developer (who does not know C, C++, or Java) will expect it to work.

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

As for casting return values: there is very little point in doing so, unless you know that you have a potentially mixed-type variable, and you want to always ensure that the return value is a specific type. This is more often the case at intermediate points in the code, rather than at the point where you're returning from a function.

一个实际例子:

<?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 的转换机制不够智能,无法优化无操作"转换.因此,强制转换 always 会导致创建变量的副本.在大多数情况下,这不是问题,但如果您经常使用这种方法,则应将其牢记在心.因此,强制转换可能会导致引用和大型数组出现意外问题.有关详细信息,请参阅 PHP 错误报告 #50894.

  • PHP's casting mechanism is not smart enough to optimize the "no-op" cast. So casting always causes a copy of the variable to be made. In most cases, this not a problem, but if you regularly use this approach, you should keep it in the back of your mind. Because of this, casting can cause unexpected issues with references and large arrays. See PHP Bug Report #50894 for more details.

在 php 中,一个太大(或太小)而无法表示为整数类型的整数将自动表示为浮点数(或双精度数,如有必要).这意味着 ($big_int + $big_int) 的结果实际上可以是一个浮点数,如果你把它转换成一个 int 结果数字将会是乱码.因此,如果您正在构建需要对大整数进行运算的函数,则应牢记这一点,并可能考虑其他一些方法.

In php, a whole number that is too large (or too small) to represent as an integer type, will automatically be represented as a float (or a double, if necessary). This means that the result of ($big_int + $big_int) can actually be a float, and if you cast it to an int the resulting number will be gibberish. So, if you're building functions that need to operate on large whole numbers, you should keep this in mind, and probably consider some other approach.

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

Sorry for the long post, but it's a topic that I've considered in depth, and through the years, I've accumulated quite a bit of knowledge (and opinion) about it. By putting it out here, I hope someone will find it helpful.

这篇关于PHP 类型转换 - 好还是坏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆