前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从源码角度看 PHP 字符串类型转换

从源码角度看 PHP 字符串类型转换

作者头像
码农UP2U
发布2020-08-26 14:44:19
3820
发布2020-08-26 14:44:19
举报
文章被收录于专栏:码农UP2U码农UP2U

PHP 的类型转换是比较方便的,但是越是容易使用的东西,底层的实现越是复杂,而且在使用中像我这样的新手也往往不清楚转换后的结果到底是什么。有时候,对于 Java 这种强类型的语言,使用的时候需要强制进行转换,这样多半转换后的结果是可以预料的,至少自己是想这么做的。

通过实例看转换

写个关于 PHP 类型转换的代码测试一下吧,看看大家是否能知道输出结果。把 各种数据类型 都转换为 字符串类型试试。

代码语言:javascript
复制
<?php

$var = false;
echo '$var:', $var, "\r\n";

$var = null;
echo '$var:', $var, "\r\n";

$var = true;
echo '$var:', $var, "\r\n";

$var = 1;
echo '$var:', $var, "\r\n";

$var = 1.1;
echo '$var:', $var, "\r\n";
$var1 = &$var;
echo '$var:', $var1, "\r\n";

$var1 = 'string111';
echo '$var:', $var1, "\r\n";

$var = [1, 2, 3];
echo '$var:', $var, "\r\n";

class Obj
{
    private $field;
}

$var = new Obj();
echo '$var:', $var, "\r\n";

代码很简单,大家可以猜猜输出结果,然后再和运行结果比对一下,运行结果如下:

代码语言:javascript
复制
$ php string.php
$var:
$var:
$var:1
$var:1
$var:1.1
$var:1.1
$var:string111
$var:
Notice: Array to string conversion in C:\Users\Administrator\Desktop\string.php
on line 24

Call Stack:
    0.0010     405568   1. {main}() C:\Users\Administrator\Desktop\string.php:0

Array
$var:
Catchable fatal error: Object of class Obj could not be converted to string in C
:\Users\Administrator\Desktop\string.php on line 32

Call Stack:
    0.0010     405568   1. {main}() C:\Users\Administrator\Desktop\string.php:0

不知道是否实际的运行结果和猜测的结果是否一致。

PHP 源码中各类型转换为字符串类型的处理

对于各种类型之间的赋值,并转换为字符串,使用真的是非常的方便。但是,实际的功劳都是 PHP 底层的复杂处理。看一下关于各种类型转换为字符串类型的源代码的处理。

代码语言:javascript
复制
ZEND_API zend_string* ZEND_FASTCALL _zval_get_string_func(zval *op) /* {{{ */
{
try_again:
  switch (Z_TYPE_P(op)) {
    case IS_UNDEF:
    case IS_NULL:
    case IS_FALSE:
      return ZSTR_EMPTY_ALLOC();
    case IS_TRUE:
      return ZSTR_CHAR('1');
    case IS_RESOURCE: {
      char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
      int len;

      len = snprintf(buf, sizeof(buf), "Resource id #" ZEND_LONG_FMT, (zend_long)Z_RES_HANDLE_P(op));
      return zend_string_init(buf, len, 0);
    }
    case IS_LONG: {
      return zend_long_to_str(Z_LVAL_P(op));
    }
    case IS_DOUBLE: {
      return zend_strpprintf(0, "%.*G", (int) EG(precision), Z_DVAL_P(op));
    }
    case IS_ARRAY:
      zend_error(E_NOTICE, "Array to string conversion");
      return zend_string_init("Array", sizeof("Array")-1, 0);
    case IS_OBJECT: {
      zval tmp;
      if (Z_OBJ_HT_P(op)->cast_object) {
        if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, IS_STRING) == SUCCESS) {
          return Z_STR(tmp);
        }
      } else if (Z_OBJ_HT_P(op)->get) {
        zval *z = Z_OBJ_HT_P(op)->get(op, &tmp);
        if (Z_TYPE_P(z) != IS_OBJECT) {
          zend_string *str = zval_get_string(z);
          zval_ptr_dtor(z);
          return str;
        }
        zval_ptr_dtor(z);
      }
      zend_error(EG(exception) ? E_ERROR : E_RECOVERABLE_ERROR, "Object of class %s could not be converted to string", ZSTR_VAL(Z_OBJCE_P(op)->name));
      return ZSTR_EMPTY_ALLOC();
    }
    case IS_REFERENCE:
      op = Z_REFVAL_P(op);
      goto try_again;
    case IS_STRING:
      return zend_string_copy(Z_STR_P(op));
    EMPTY_SWITCH_DEFAULT_CASE()
  }
  return NULL;
}
/* }}} */

从上面的源码中可以看出,对于类型的转换,PHP 底层的源码使用了 switch ... case 的结构,在进行转换的时候需要对逐个的类型进行匹配后,再进行转换。当然,从源码的角度去看待上面的 PHP 类型转换的代码就非常的清晰明了了。

最后

读 PHP 的源码有一段时间了,进度比较慢,说实话,对于写 PHP 的代码没有什么提高,或者对我来说没有遇到什么让我提高的地方。单纯的出于对知识求甚解的原因吧。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农UP2U 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档