浅析PHP原理之变量(Variables inside PHP)

或许你知道,或许你不知道,PHP是一个弱类型,动态的脚本语言。所谓弱类型,就是说PHP并不严格验证变量类型(严格来讲,PHP是一个中强类型语言,这部分内容会在以后的文章中叙述),在申明一个变量的时候,并不需要显示指明它保存的数据的类型:


代码如下:

<?php
  $var = 1; //int
  $var = "laruence"; //string
  $var = 1.0002; //float
  $var = array(); // array
  $var = new Exception('error'); //object;

动态语言,就是说,PHP的语言结构在运行期是可以改变的,比如我们在运行期require一个函数定义文件,从而导致语言的函数表动态的改变。

所谓脚本语言,就是说,PHP并不是独立运行的,要运行PHP我们需要PHP解析器:


代码如下:

/usr/bin/php -f example.ph

我前面的文章中已经讲过,PHP的执行是通过Zend engine(ZE, Zend引擎), ZE是用C编写的,大家都知道C是一个强类型语言,也就是说,在C中所有的变量在它被声明到最终销毁,都只能保存一种类型的数据。 那么PHP是如何在ZE的基础上实现弱类型的呢?

在PHP中,所有的变量都是用一个结构-zval来保存的, 在Zend/zend.h中我们可以看到zval的定义:


代码如下:

typedef struct _zval_struct {
    zvalue_value value;
    zend_uint refcount;
    zend_uchar type;
    zend_uchar is_ref;
  } zval;

其中zvalue_value是真正保存数据的关键部分,现在到了揭晓谜底的时候了,PHP是如何在ZE的基础上实现弱类型的呢? 因为zvalue_value是个联合体(union),


代码如下:

typedef union _zvalue_value {
    long lval;
    double dval;
    struct {
        char *val;
        int len;
    } str;
    HashTable *ht;
    zend_object_value obj;
} zvalue_value;

那么这个结构是如何储存PHP中的多种类型的呢?

PHP中常见的变量类型有:
1. 整型/浮点/长整型/bool值 等等
2. 字符串
3. 数组/关联数组
4. 对象
5. 资源

PHP根据zval中的type字段来储存一个变量的真正类型,然后根据type来选择如何获取zvalue_value的值,比如对于整型和bool值:


代码如下:

zval.type = IS_LONG;//整形
   zval.type = IS_BOOL;//布尔

就去取zval.value.lval,对于bool值来说lval∈(0|1);
如果是双精度,或者float则会去取zval.value的dval。
而如果是字符串,那么:


代码如下:

zval.type = IS_STRIN

这个时候,就会取:
zval.value.str
而这个也是个结构,存有C分格的字符串和字符串的长度。
而对于数组和对象,则type分别对应IS_ARRAY, IS_OBJECT, 相对应的则分别取zval.value.ht和obj
比较特别的是资源,在PHP中,资源是个很特别的变量,任何不属于PHP内建的变量类型的变量,都会被看作成资源来进行保存,比如,数据库句柄,打开的文件句柄等等。 对于资源:


代码如下:

type = IS_RESOURC

这个时候,会去取zval.value.lval, 此时的lval是个整型的指示器, 然后PHP会再根据这个指示器在PHP内建的一个资源列表中查询相对应的资源(这部分的内容,我以后会单独开一个篇文章来介绍),目前,你只要知道此时的lval就好像是对应于资源链表的偏移值。


代码如下:

ZEND_FETCH_RESOURCE(con, type, zval *, default, resource_name, resource_type);

借用这样的机制,PHP就实现了弱类型,因为对于ZE的来说,它所面对的永远都是同一种类型,那就是zval。

(0)

相关推荐

  • 浅析php变量修饰符static的使用

    静态变量仅在局部函数域中存在,但当程序执行离开此作用域时,其值并不丢失.看看下面的例子: 复制代码 代码如下: function test(){static $a=0;$a++;echo $a;} test();//1test();//2test();//3Note: 静态变量可以按照上面的例子声明.如果在声明中用表达式的结果对其赋值会导致解析错误. 复制代码 代码如下: static $a=0+1;static $a=sqrt(121); 像上面的赋值方式会报错,不信你试试

  • 浅析php变量作用域的一些问题

    昨晚就与到这么一个问题,是全局变量在函数中的问题.今天搜索了一下,发现一篇相当不错的文章,讲了php中的变量作用域.是一位网友翻译的在这贴一下: 变量范围变量的范围即它定义的上下文背景(译者:说白了,也就是它的生效范围).大部分的 PHP 变量只有一个单独的范围.这个单独的范围跨度同样包含了 include 和 require 引入的文件.范例: 复制代码 代码如下: <?php$a = 1;include "b.inc";?> 这里变量 $a 将会在包含文件 b.inc

  • 解析在PHP中使用全局变量的几种方法

    简介即使开发一个新的大型PHP程序,你也不可避免的要使用到全局数据,因为有些数据是需要用到你的代码的不同部分的.一些常见的全局数据有:程序设定类.数据库连接类.用户资料等等.有很多方法能够使这些数据成为全局数据,其中最常用的就是使用"global"关键字申明,稍后在文章中我们会具体的讲解到.使用"global"关键字来申明全局数据的唯一缺点就是它事实上是一种非常差的编程方式,而且经常在其后导致程序中出现更大的问题,因为全局数据把你代码中原本单独的代码段都联系在一起了

  • 浅析PHP原理之变量分离/引用(Variables Separation)

    首先我们回顾一下zval的结构: 复制代码 代码如下: struct _zval_struct {        /* Variable information */        zvalue_value value; /* value */        zend_uint refcount;        zend_uchar type; /* active type */        zend_uchar is_ref;}; 其中的refcount和is_ref字段我们一直都没有介绍过

  • 浅析PHP原理之变量(Variables inside PHP)

    或许你知道,或许你不知道,PHP是一个弱类型,动态的脚本语言.所谓弱类型,就是说PHP并不严格验证变量类型(严格来讲,PHP是一个中强类型语言,这部分内容会在以后的文章中叙述),在申明一个变量的时候,并不需要显示指明它保存的数据的类型: 复制代码 代码如下: <?php  $var = 1; //int  $var = "laruence"; //string  $var = 1.0002; //float  $var = array(); // array  $var = ne

  • 深入浅出理解PHP原理之变量赋值

    PHP的变量赋值 这个标题估计很多人会不屑一顾,变量赋值?excuse me?我们学开发的第一课就会了好不好.但是,就是这样基础的东西,反而会让很多人蒙圈,比如,值和引用的关系.今天,我们就来具体讲讲. 首先,定义变量和赋值这个不用多说了吧 $a = 1; $b = '2'; $c = [4, 5, 6]; $d = new stdClass(); 四个变量,分别定义了整型.字符串.数组的对象.这也是我们天天要打交道的四种类型. 然后,变量给变量赋值. $a1 = $a; $b1 = $b; $

  • Go语言编译原理之变量捕获

    目录 前言 变量捕获概述 变量捕获底层实现 总结 前言 在前边的几篇文章中已经基本分享完了编译器前端的一些工作,后边的几篇主要是关于编译器对抽象语法树进行分析和重构,然后完成一系列的优化,其中包括以下五个部分: 变量捕获 函数内联 逃逸分析 闭包重写 遍历函数 后边的五篇文章主要就是上边这五个主题,本文分享的是变量捕获,变量捕获主要是针对闭包场景的,因为闭包函数中可能引用闭包外的变量,因此变量捕获需要明确在闭包中通过值引用或地址引用的方式来捕获变量 变量捕获概述 下边通过一个示例来看一下什么是变

  • 浅析bootstrap原理及优缺点

    网格系统的实现原理,是通过定义容器大小,平分12份(也有平分成24份或32份,但12份是最常见的),再调整内外边距,最后结合媒体查询,就制作出了强大的响应式网格系统.Bootstrap框架中的网格系统就是将容器平分成12份. bootstrap优缺点: 1.bootstap最近发布了bootstrap4,拥有了box-flex布局等更新,紧跟最新的web技术的发展 2.比较成熟,在大量的项目中充分的使用和测试 3.拥有完善的文档,使用起来更方便 4.有大量的组件样式,接受定制 缺点: 1.如果有

  • 深入浅析vue全局环境变量和模式

    我们可以在项目根目录中的下列文件来指定环境变量: .env                # 在所有的环境中被载入 .env.local          # 在所有的环境中被载入,但会被 git 忽略 .env.[mode]         # 只在指定的模式中被载入 .env.[mode].local   # 只在指定的模式中被载入,但会被 git 忽略 一个环境文件只包含环境变量的"键=值"对,并且必须以VUE_APP开始: FOO=bar     //无效 VUE_APP_SE

  • Python接口自动化浅析数据驱动原理

    在上一篇Python接口自动化测试系列文章:Python接口自动化浅析登录接口测试实战,主要介绍接口概念.接口用例设计及登录接口测试实战. 以下主要介绍使用openpyxl模块操作excel及结合ddt实现数据驱动. 在此之前,我们已经实现了用unittest框架编写测试用例,实现了请求接口的封装,这样虽然已经可以完成接口的自动化测试,但是其复用性并不高. 我们看到每个方法(测试用例)的代码几乎是一模一样的,试想一下,在我们的测试场景中, 一个登录接口有可能会有十几条到几十条测试用例,如果每组数

  • 浅析JavaScript中的变量提升

    目录 前言: 函数提升 var变量提升 let & const提升 Class提升 前言: JavaScript中奇怪的一点是你可以在变量和函数声明之前使用它们.就好像是变量声明和函数声明被提升了代码的顶部一样. sayHi() // Hi there! function sayHi() { console.log('Hi there!') } name = 'John Doe' console.log(name) // John Doe var name 然而JavaScript并不会移动你的

  • MySQL详细讲解变量variables的用法

    目录 变量 variables 1.系统变量 1.1.查看系统变量 1.2.修改系统变量 2.会话变量 3.局部变量 4.变量作用域 4.1.局部作用域 4.2.会话作用域 4.3.全局作用域 变量 variables MySQL本质是一种编程语言 1.系统变量 对所有用户客户端都有效 1.1.查看系统变量 1.方式一 show variables [like 'pattern']; 示例 mysql> show variables like 'autocommit'; +-----------

  • OB系统变量Variables及ODC管理会话功能详解

    目录 参数和变量 Session variables vs Global variables 常用的OB系统变量 (Variables) ODC管理会话功能支持查看和修改会话属性 小结 参数和变量 Session variables vs Global variables • 会话变量:Session 级修改 (只对本会话生效).当客户端连接到数据库后,数据库会复制全局变量以自动生成会话变量.会话变量的修改只对当前会话生效. • set ob_trx_timeout = 200000000 •

随机推荐