PHP中强制类型转换的示例详解

前言

学过静态语言开发的朋友对类型转换不会陌生,比如Java、C#、C++等。静态语言的好处就是变量强制必须指定类型,这也是编译的要求,所以大部分编译型的语言都会有强制变量类型的要求。而PHP据说也会在PHP8中加入JIT实现编译功能,并且在7.4中就会引入变量声明时的类型指定。下面我们先看看目前PHP中的参数类型及返回值类型的使用。

1function add(int $a, float $b) : int{
2 return (int) $a + $b;
3}

上述代码中,方法参数中定义了参数的类型,包括一个int类型的a和一个float类型的b。然后在方法后面定义了方法的返回值必须是int类型。我们知道,如果计算表达式中出现了float类型,那么计算结果会变成float类型。这个方法需要返回的是一个int类型。因此我们使用了一个强制类型转换(int)。在定义了参数类型和返回值类型后,如果传递或者返回的类型不一致,就会报错。

参数类型和返回值类型最好在7以上的版本使用。基本类型如int、float等的参数类型声明都是7以后才支持的,详情参见文档:

https://www.php.net/manual/zh/functions.arguments.php

我们通过(int)、(float)、(bool)等就可以实现PHP的类型强制转换,和C基本上一样。文档中关于可以强制转换的包括如下类型:

  • (int), (integer) - 转换为整形 integer
  • (bool), (boolean) - 转换为布尔类型 boolean
  • (float), (double), (real) - 转换为浮点型 float
  • (string) - 转换为字符串 string
  • (array) - 转换为数组 array
  • (object) - 转换为对象 object
  • (unset) - 转换为 NULL (PHP 5)
  • (binary) 转换和 b 前缀转换支持为 PHP 5.2.1 新增

(int), (integer)

如果是布尔值,转换结果为false变成0,true变成1

如果是float,向下取整,如7.99会转换为7

如果是字符串,字符串从头开始查找,开头第一个是数字会直接变成该转换结果,如果开头没有数字返回0

其他类型转换在文档中并没有定义,文档提示为“没有定义从其它类型转换为整型的行为。不要依赖任何现有的行为,因为它会未加通知地改变。”,但我们通过测试,可以发现对于其他类型的转换是通过多次的类型转换达成的,比如数组类型转换为int类型,是根据数组是否包含内容转换为bool类型后再转换为int类型

// (int)(integer)

var_dump((int) true); // 1
var_dump((int) false); // 0

var_dump((int) 7.99); // 7

var_dump((int) "35 ok"); // 35
var_dump((int) "ok 77"); // 0
var_dump((int) "ok yes"); // 0

var_dump((int) []); // 0
var_dump((int) [3,4,5]); // 1

(bool)(boolean)

当转换为 boolean 时,以下值被认为是 FALSE:

  • 布尔值 FALSE 本身
  • 整型值 0(零)
  • 浮点型值 0.0(零)
  • 空字符串,以及字符串 "0"
  • 不包括任何元素的数组
  • 特殊类型 NULL(包括尚未赋值的变量)
  • 从空标记生成的 SimpleXML 对象

所有其它值都被认为是 TRUE(包括任何资源 和 NAN)

这里需要注意的是,负数也会是TRUE,只有0是FASLE

// (bool)(boolean)

var_dump((bool) 0); // false
var_dump((bool) 1); // true
var_dump((bool) -1); // true

var_dump((bool) 0.0); // false
var_dump((bool) 1.1); // true
var_dump((bool) -1.1); // true

var_dump((bool) ""); // false
var_dump((bool) "0"); // false
var_dump((bool) "a"); // true

var_dump((bool) []); // false
var_dump((bool) ['a']); // true

$a;
var_dump((bool) $a); // false
var_dump((bool) NULL); // false

(string)

  • 布尔值,false转换为空字符串"",true转换为"1"
  • int或float类型,转换为字符串形式的字面量,如1转换为"1"
  • 数组和对象分别转换为"Array"和"Object"字面量
  • 资源类型会被转换为"Resource id #1"形式的字面量
  • NULL转换为空字符串""

直接把 array,object 或 resource 转换成 string 不会得到除了其类型之外的任何有用信息。可以使用函数 print_r() 和 var_dump() 列出这些类型的内容

注:测试结果,对象类型需要实现__tostring()魔术函数,否则报错无法转换为string类型

// (string)

var_dump((string) true); // "1"
var_dump((string) false); // ""

var_dump((string) 55); // "55"
var_dump((string) 12.22); // "12.22"

var_dump((string) ['a']); // "Array"
class S{
 function __tostring(){
 return "S";
 }
}
var_dump((string) new S()); // "S"

var_dump((string) NULL); // ""

(array)

对于任意 integer,float,string,boolean 和 resource 类型,如果将一个值转换为数组,将得到一个仅有一个元素的数组,其下标为 0,该元素即为此标量的值。换句话说(array)scalarValue 与 array(scalarValue) 是完全一样的

如果一个 object 类型转换为 array,则结果为一个数组,其单元为该对象的属性。键名将为成员变量名,不过有几点例外:整数属性不可访问;私有变量前会加上类名作前缀;保护变量前会加上一个 '*' 做前缀。这些前缀的前后都各有一个 NULL 字符

将 NULL 转换为 array 会得到一个空的数组

// (array)

var_dump((array) 1);
var_dump((array) 2.2);

var_dump((array) "a");

var_dump((array) true);

class Arr
{
 public $a = 1;
 private $b = 2.2;
 protected $c = "f";
}
class ChildArr extends Arr
{
 public $a = 2;
 private $d = "g";
 private $e = 1;
}
var_dump((array) new Arr());
var_dump((array) new ChildArr());

var_dump((array) null);

(object)

如果将一个对象转换成对象,它将不会有任何变化。如果其它任何类型的值被转换成对象,将会创建一个内置类 stdClass 的实例。如果该值为 NULL,则新的实例为空。array 转换成 object 将使键名成为属性名并具有相对应的值

注意:使用 PHP 7.2.0 之前的版本,数字键只能通过迭代访问

// (object)

var_dump((object) 1);
var_dump((object) 1.1);
var_dump((object) "string");
var_dump((object) true);
var_dump((object) NULL);

var_dump((object) [1, 2, 3]);
var_dump((object) ["a" => 1, "b" => 2, "c" => 3]);

(unset)

使用 (unset) $var 将一个变量转换为 null 将不会删除该变量或 unset 其值。仅是返回 NULL 值而已

// (unset)

var_dump((unset) 1);
var_dump((unset) 1.1);
var_dump((unset) "string");
var_dump((unset) true);
var_dump((unset) null);

var_dump((unset) [1, 2, 3]);
var_dump((unset) new \stdClass());

(binary)

将所有类型转换为二进制字符串。二进制字符串是区别于传统常用的普通php的Unicode字符串。二进制字符串是字节字符串,没有字符集。具体的区别就类似于数据库中的binary和char类型及blob和text类型

在日常的开发中基本用不到,了解即可

// (binary)

var_dump((binary) 1);
var_dump((binary) 1.1);
var_dump((binary) "string");
var_dump((binary) true);
var_dump((binary) null);

var_dump((binary) [1, 2, 3]);
var_dump((binary) new S());

以上就是我们的强制类型转换的所有类型,其中有一些类型的转换中提到了资源类型(Resource),但是并没有资源类型的强制转换。因为资源类型大多是一些句柄操作,如数据库链接、文件读写等,将其它类型强制转换为资源类型没有意义。

本文内容会经常出现在面试题中,而且在实际开发中的很多逻辑判断出现的BUG也常常是由于PHP的自动类型转换所导致的,所以这篇文章好好收藏多拿出来看看绝对会让你有意想不到的收获哦!!

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/201910/source/php%E4%B8%AD%E7%9A%84%E5%BC%BA%E5%88%B6%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2.php

参考文档:

https://www.php.net/manual/zh/language.types.type-juggling.php#language.types.typecasting

总结

到此这篇关于PHP中强制类型转换的文章就介绍到这了,更多相关PHP强制类型转换内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 解析PHP强制转换类型及远程管理插件的安全隐患

    远程管理插件是目前广受WordPress站点管理员欢迎的实用工具,它允许用户同时对多个站点执行相同的操作,如更新到最新的发行版或安装插件等.但是,为了实现这些操作,客户端插件需要赋予远程用户很大的权限.因此,确保管理服务器和客户端插件之间的通信安全且不能被攻击者伪造就变得相当重要了.本文浅析几款可用插件,利用其弱点,攻击者甚至可以完全危及到运行这些插件的站点本身. ManageWP, InfiniteWP, and CMS Commander 这三个服务有着相同的客户端插件基础代码(目测最初是M

  • PHP数组Key强制类型转换实现原理解析

    PHP是弱类型语言,就像JavaScript一样,在定义变量时,不需要强制指定变量的类型.同时,PHP又有着强大的数组功能,数组的Key即可以是普通的数字类型下标,也可以是字符串类型的Hash键值,那么,当一个数组的Key同时拥有字符串和数字时,会产生什么情况呢? 首先来看下面这样一段代码: $arr = [ "1" => "a", "01" => "b", 1 => "aa", 1.1

  • 浅谈PHP强制类型转换,慎用!

    PHP是一门弱类型的语言.这是它的优势和特点,但是有的时候你又不得不对类型进行相应的转换. 这个时候问题就来了.因为很多情况下,你会发现转换类型之后得到的数据和预期的值相差老大一截. 这里我以强制转换为整形作为例子. 看下面的代码,可以说你绝对不可能说出正确的答案.echo (int) 123.999999999999999; echo (int)   -1.999999999999999;echo (int)   -1.9999999999999999; echo (int)   -0.999

  • php foreach 参数强制类型转换的问题

    所以,为了防止这样的信息出现,我使用foreach的时候,都会把参数进行强制类型转换,形势如下: foreach((array)$arr as $key => $value); 这样做一直相安无事,就在前几天,突然出现了问题.我强制类型转换以后不能正常的调用object的方法了. 复制代码 代码如下: <?php class service implements Iterator{ function __construct($service_define,$filter=null){ $thi

  • PHP 变量类型的强制转换

    也就是说,如果把一个字符串值赋给变量 var,var 就成了一个字符串.如果又把一个整型值赋给 var,那它就成了一个整数. PHP 中的类型强制转换和 C 中的非常像:在要转换的变量之前加上用括号括起来的目标类型. 复制代码 代码如下: <?php $foo = 10; echo "转换前:\$foo=".$foo; //输出一个整数 echo "<br/>" //输出:$foo=10 echo "<br/>";

  • PHP中强制类型转换的示例详解

    前言 学过静态语言开发的朋友对类型转换不会陌生,比如Java.C#.C++等.静态语言的好处就是变量强制必须指定类型,这也是编译的要求,所以大部分编译型的语言都会有强制变量类型的要求.而PHP据说也会在PHP8中加入JIT实现编译功能,并且在7.4中就会引入变量声明时的类型指定.下面我们先看看目前PHP中的参数类型及返回值类型的使用. 1function add(int $a, float $b) : int{ 2 return (int) $a + $b; 3} 上述代码中,方法参数中定义了参

  • C语言中强制地址跳转详解

    C语言中强制地址跳转详解 #define jump(TargetAddr ) (*((void(*)())(TargetAddr))() 第一个(( void( * )(  )) ,意思为强制类型转换为一个无形参,无返回值的函数指针,(*(TargetAddr))为跳转地址,但是函数指针变量不能为常数所以要加((void( * )(  )) 进行强制类型转换.最后一个()为执行的意思. 整一条指定的目的是为了跳转到一个绝对地址执行函数. 1.在单片机中可以实现软件复位,比如跳转到0地址. 2.如

  • C语言中的正则表达式使用示例详解

    正则表达式,又称正规表示法.常规表示法(英语:Regular Expression,在代码中常简写为regex.regexp或RE).正则表达式是使用单个字符串来描述.匹配一系列符合某个句法规则的字符串. 在c语言中,用regcomp.regexec.regfree 和regerror处理正则表达式.处理正则表达式分三步: 编译正则表达式,regcomp: 匹配正则表达式,regexec: 释放正则表达式,regfree. 函数原型 /* 函数说明:Regcomp将正则表达式字符串regex编译

  • Flutter 中 Dart的Mixin示例详解

    原文在这里.写的不错,推荐各位看原文. 这里补充一下Mixin的定义: 只要一个类是继承自Object的而且没有定义构造方法,那么这个类可以是一个Mixin了.当然,如果你想让mixin的定义更加的清晰,可以使用mixin关键字开头来定义.具体请参考这里 原文截图体会一下风格. 正文 在经典的面向对象编程语言里一定会有常规的类,抽象类和接口.当然,Dart也有它自己的接口,不过那是另外的文章要说的.有的时候阴影里潜伏者另外的野兽:Mixin!这是做什么的,如何使用?我们来一起发现. 没有mixi

  • shrio中hashedCredentialsMatcher密码匹配示例详解

    类图如下: SimpleCredentialsMatcher是明文匹配,也是shrio框架默认的比对方式,网上的例子多是此方式.实际项目中,数据库中的密码一般是密文,此时密码的匹配需使用HashedCredentialsMatcher完成. 处理过程 在controller中通过Subject的login(token)将接收过来用户账号和密码(明文)交给shrio框架,示例代码如下 其次通过HashedCredentialsMatcher告诉shrio使用加密方式: 最后通过Authorizin

  • Java中的反射机制示例详解

    目录 反射 什么是Class类 获取Class实例的三种方式 通过反射创建类对象 通过反射获取类属性.方法.构造器 更改访问权限和实例赋值 运用场景 反射 反射就是把Java类中的各个成分映射成一个个的Java对象.即在运行状态中,对于任意一个类,都能够知道这个类的所以属性和方法:对于任意一个对象,都能调用它的任意一个方法和属性.这种动态获取信息及动态调用对象方法的功能叫Java的反射机制 每一个Java程序执行必须通过编译.加载.链接和初始化四个阶段 1.编译:将.java.文件编译成字节码.

  • Python中图像算术运算的示例详解

    目录 介绍 算术运算:图像相加 算术运算:图像减法 位运算 介绍 还记得你在小学时学习如何加减数字吗?现在,你也可以对图像做同样的事情! 输入图像可以进行算术运算,例如加法.减法和按位运算(AND.OR.NOT.XOR).这些操作可以帮助提高输入照片的质量. 在本文中,你将了解使用 OpenCV Python 包对图像执行算术和按位运算的步骤.让我们开始吧! 对图像进行算术运算是什么意思? 因此,假设我们希望合并两张单独的照片中的两个像素.我们怎样才能将它们合并? 让我们想象以下场景.第一个像素

  • JavaScript中事件委托的示例详解

    目录 事件流 事件委托 结尾 大家好,我是前端西瓜哥.今天我们来认识一下事件委托. 所谓事件委托,就是将原本应该在当前元素绑定的事件,放到它的祖先元素上,让祖先元素来委托处理. 事件流 事件流指从页面中接收事件的顺序,也可理解为事件在页面中传播的顺序. 事件流由两阶段组成: 捕获事件 冒泡事件 我们通常用 addEventListener 给元素添加事件: document.querySelector('#card')addEventListener( 'click', function (ev

  • Swift 中的 JSON 反序列化示例详解

    目录 业界常用的几种方案 手动解码方案,如 Unbox(DEPRECATED) 阿里开源的 HandyJSON 基于 Sourcery 的元编程方案 Swift build-in API Codable 属性装饰器,如 BetterCodable 各个方案优缺点对比 Codable 介绍 原理浅析 Decoder.Container 协议 自研方案 功能设计 Decoder.Container 具体实现 再议 PropertyWrapper 应用场景示例 单元测试 性能对比 业界常用的几种方案

  • Java中随机函数变换的示例详解

    目录 说明 解决的问题 问题1 问题2 问题3 问题4 说明 本示例中基于 Java ,其他语言也有类似的 API 解决的问题 问题1 Java 中 Math.random()函数是等概率返回区间[0,1)中的任意一个小数.即x < 1情况下,[0,x)中的数出现的的概率是x,如果我们要将x < 1情况下,[0,x)中的数出现的的概率调整成x^2,应该如何做? 问题1思路 由于[0,x)的概率是x,那么调用两次Math.random(),如果较大的那个值也要在[0,x)区间内,那么两次调用都必

随机推荐