php执行流程

目的:
本文主要介绍PHP执行流程,目的是梳理php代码是如何最终转换成为机器二进制指令而被执行的
参考文章:https://blog.csdn.net/diavid/article/details/81035188

PHP层执行流程主要以下四步:
一. Scanning (Lexing) ,将PHP代码转换为语言片段(Tokens)
PHP4.2+开始提供了一个函数叫token_get_all ,这个函数就可以讲一段PHP代码 Scanning成Tokens
eg:

$code='<?php
            $a = 1 + 1;
            echo $a;
          ?>';
        $tokens=token_get_all($code);
        print_r($tokens);
        exit();
1
2
3
4
5
6
7
输出结果:Array ( [0] => Array ( [0] => 379 [1] => 1 ) [1] => Array ( [0] => 382 [1] => [2] => 2 ) [2] => Array ( [0] => 320 [1] => $a [2] => 2 ) [3] => Array ( [0] => 382 [1] => [2] => 2 ) [4] => = [5] => Array ( [0] => 382 [1] => [2] => 2 ) [6] => Array ( [0] => 317 [1] => 1 [2] => 2 ) [7] => Array ( [0] => 382 [1] => [2] => 2 ) [8] => + [9] => Array ( [0] => 382 [1] => [2] => 2 ) [10] => Array ( [0] => 317 [1] => 1 [2] => 2 ) [11] => ; [12] => Array ( [0] => 382 [1] => [2] => 2 ) [13] => Array ( [0] => 328 [1] => echo [2] => 3 ) [14] => Array ( [0] => 382 [1] => [2] => 3 ) [15] => Array ( [0] => 320 [1] => $a [2] => 3 ) [16] => ; [17] => Array ( [0] => 382 [1] => [2] => 3 ) [18] => Array ( [0] => 381 [1] => ?> [2] => 4 ) )

返回的结果中, 源码中的字符串,字符,空格,都会原样返回。每个源代码中的字符,都会出现在相应的顺序处。而其他的比如标签,操作符,语句,都会被转换成一个包含俩部分的Array: Token ID (也就是在Zend内部的改Token的对应码,比如,T_ECHO,T_STRING),和源码中的原来的内容。

二. Parsing , 将Tokens转换成简单而有意义的表达式
Parsing首先会丢弃Tokens Array中的多余的空格,然后将剩余的Tokens转换成一个一个的简单的表达式
eg:

1. echo a constant string

2. add two numbers together

3. store the result of the prior expression to a variable

4. echo a variable
1
2
3
4
5
6
7
三. Compilation , 将表达式编译成Opocdes
Compilation阶段,它会把Tokens编译成一个个op_array,每个op_arrayd包含如下5个部分:

1. Opcode数字的标识,指明了每个op_array的操作类型,比如add,echo

2. 结果存放Opcode结果

3. 操作数1给Opcode的操作数

4. 操作数2

5. 扩展值1个整形用来区别被重载的操作符
1
2
3
4
5
6
7
8
9
注:PHP 5.5及以后自带opcache缓存拓展,在php.ini开启后可以对Opcode 进行缓存,这样每次有请求来临的时候,就不需要重复执行前面3步,从而能大幅的提高PHP的执行速度。

四. Execution , 顺次执行Opcodes,每次一条,从而实现PHP脚本的功能。
上面的opcode 指令并不是二进制的机器码,而是C实现php软件时定义的指令,最后指令的执行都得调用c语言实现的方法,而这些方法都是zendVM 提前实现,并经过编译成汇编,最后汇编再转换为目标机器的二进制码,这种方式叫解析执行,JVM解析执行java 二进制码也基本是这个逻辑;
另外,除了解析执行, jvm 跟zendvm(PHP 8后) 都实现了即时编译(Just-In-Time compilation,JIT),即将一个方法中包含的所有字节码编译成机器码后再执行,如下图;

最后贴上一个PHP 完整执行流程图


后语:从上面的流程看 php 如果开启opcache 整个执行流程应该跟java是差不多,但为啥大家都说java性能要比PHP 高很多呢?后面将会对java 为啥比php快做一个比较完整的分析;
 

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在TP6.0中,事件机制是通过事件管理器(Event)来实现的。事件管理器是一个全局单例对象,可以在应用程序的任何地方使用。事件管理器主要负责事件的注册、触发和监听。 以下是TP6.0中事件执行流程: 1. 注册事件 在应用程序的任何地方,都可以通过事件管理器注册事件。注册事件时,需要指定事件名称和事件处理函数。事件名称可以是任何字符串,事件处理函数可以是闭包、方法或者类静态方法。 例如: ```php // 注册事件 \think\facade\Event::listen('user_login', function ($user) { // 处理用户登录事件 ... }); ``` 2. 触发事件 当应用程序执行到某个位置时,可以通过事件管理器触发事件。触发事件时,需要指定事件名称和事件参数。事件参数可以是任何类型的数据。 例如: ```php // 触发事件 \think\facade\Event::trigger('user_login', $user); ``` 3. 执行事件处理函数 当事件被触发时,事件管理器会自动执行注册的事件处理函数。事件处理函数会按照注册的顺序执行,直到所有的事件处理函数都执行完毕。 例如: ```php // 执行事件处理函数 function handleUserLogin($user) { // 处理用户登录事件 ... } ``` 4. 返回事件结果 事件处理函数可以返回任何类型的数据,这些数据会被收集到一个数组中,作为最终的事件结果返回。事件结果可以被其他的事件处理函数使用。 例如: ```php // 返回事件结果 function handleUserLogin($user) { // 处理用户登录事件 ... return ['user' => $user, 'time' => time()]; } ``` 以上就是TP6.0中事件执行流程。通过事件机制,我们可以实现应用程序的解耦和扩展,让应用程序更加灵活和可维护。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值