美文网首页PHP实战
从源码角度看 PHP 字符串类型转换

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

作者: 码农UP2U | 来源:发表于2019-11-17 20:14 被阅读0次

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

    通过实例看转换

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

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

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

    $ 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 底层的复杂处理。看一下关于各种类型转换为字符串类型的源代码的处理。

    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 的代码没有什么提高,或者对我来说没有遇到什么让我提高的地方。单纯的出于对知识求甚解的原因吧。



    我的微信公众号:“码农UP2U”
    我的公众号

    相关文章

      网友评论

        本文标题:从源码角度看 PHP 字符串类型转换

        本文链接:https://www.haomeiwen.com/subject/gvhmictx.html