本文由Younes Rafie进行了同行评审。感谢SitePoint所有的同行评审员制作SitePoint内容的最佳状态!
钥匙要点
解释
$code = <<<'code' <span><span><?php </span></span><span><span>$a = 1; </span></span><span>code<span>; </span></span><span> </span><span><span>$tokens = token_get_all($code); </span></span><span> </span><span><span>foreach ($tokens as $token) { </span></span><span> <span>if (is_array($token)) { </span></span><span> <span>echo "Line <span><span>{$token[2]}</span>: "</span>, token_name($token[0]), " ('<span><span>{$token[1]}</span>')"</span>, PHP_EOL; </span></span><span> <span>} else { </span></span><span> <span>var_dump($token); </span></span><span> <span>} </span></span><span><span>} </span></span>
>从上述输出中有几个值得注意的点。第一个点是,并非所有源代码的所有部分都命名为令牌。相反,某些符号本身被视为令牌(例如=,;,:,?等)。第二点是,Lexer实际上做的不只是简单地输出一个令牌流。在大多数情况下,它也存储了lexeme(由令牌匹配的值)和匹配令牌的行号(用于堆栈跟踪之类的内容)。
阶段2 - 解析>生成的解析器阶段将令牌流从Lexer作为输入中获取,并有两个作业。首先,它通过尝试将其与BNF语法文件中定义的任何语法规则相匹配,从而验证令牌顺序的有效性。这样可以确保令牌流中的代币形成有效的语言构造。解析器的第二个作业是生成
抽象语法树(AST) - 下一阶段将使用的源代码的树视图(汇编)。
我们可以使用php-ast扩展名来查看
Line 1: T_OPEN_TAG ('<?php ') Line 2: T_VARIABLE ('$a') Line 2: T_WHITESPACE (' ') string(1) "=" Line 2: T_WHITESPACE (' ') Line 2: T_LNUMBER ('1') string(1) ";"
$code = <<<'code' <span><span><?php </span></span><span><span>$a = 1; </span></span><span>code<span>; </span></span><span> </span><span><span>print_r(ast<span>\parse_code</span>($code, 30)); </span></span>
>标志 - 一个指定过载行为的整数(例如,ASTAST_BINARD_OP节点将具有区分发生哪些二进制操作的标志)
Lineno汇编阶段消耗了AST,它通过递归穿越树来发出opcods。这个阶段还进行了一些优化。这些包括通过字面论据(例如strlen(“ ABC”)到int(3))和折叠持续的数学表达式(例如60 * 60 * 24 to int(86400))。
>我们可以在此阶段以多种方式检查OpCode输出,包括OPCACHE,VLD和PHPDBG。我将使用VLD为此,因为我觉得输出更友好。>让我们看看以下file.php脚本的输出是什么:
执行以下命令:
$code = <<<'code' <span><span><?php </span></span><span><span>$a = 1; </span></span><span>code<span>; </span></span><span> </span><span><span>$tokens = token_get_all($code); </span></span><span> </span><span><span>foreach ($tokens as $token) { </span></span><span> <span>if (is_array($token)) { </span></span><span> <span>echo "Line <span><span>{$token[2]}</span>: "</span>, token_name($token[0]), " ('<span><span>{$token[1]}</span>')"</span>, PHP_EOL; </span></span><span> <span>} else { </span></span><span> <span>var_dump($token); </span></span><span> <span>} </span></span><span><span>} </span></span>
我们的输出是:
Line 1: T_OPEN_TAG ('<?php ') Line 2: T_VARIABLE ('$a') Line 2: T_WHITESPACE (' ') string(1) "=" Line 2: T_WHITESPACE (' ') Line 2: T_LNUMBER ('1') string(1) ";"
> Opcodes类似于原始源代码,足以与基本操作一起进行。 (我不会深入研究本文中的opcodes的详细信息,因为这本身将需要几个整个文章。)在上面脚本中没有在OpCode级别上应用优化,但是正如我们所看到的,编译阶段通过解决恒定条件(php_version ==='7.1.0-dev')来做出一些。
$code = <<<'code' <span><span><?php </span></span><span><span>$a = 1; </span></span><span>code<span>; </span></span><span> </span><span><span>print_r(ast<span>\parse_code</span>($code, 30)); </span></span>
>
>命令:
>输出:
ast\Node Object ( [kind] => 132 [flags] => 0 [lineno] => 1 [children] => Array ( [0] => ast\Node Object ( [kind] => 517 [flags] => 0 [lineno] => 2 [children] => Array ( [var] => ast\Node Object ( [kind] => 256 [flags] => 0 [lineno] => 2 [children] => Array ( [name] => a ) ) [expr] => 1 ) ) ) )
>我们可以看到恒定条件已被删除,并且两个回声指令已被压缩到单个指令中。这些只是对Opcache在脚本的Opcodes上进行的许多优化的味道。不过,我不会浏览本文的各种优化级别,因为这本身也是一篇文章。
>阶段4 - 解释<span>if (PHP_VERSION === '7.1.0-dev') { </span> <span>echo 'Yay', PHP_EOL; </span><span>} </span>
>最后阶段是对opcodes的解释。这是Opcodes在Zend Engine(ZE)VM上运行的地方。对于这个阶段,实际上几乎没有什么可说的(至少从高级角度来看)。输出几乎是您通过echo,print,var_dump等命令输出输出的任何内容。
>因此,这是一个有趣的事实,而不是在此阶段挖掘任何复杂的事实:PHP在生成自己的VM时需要自己作为依赖性。这是因为VM是由PHP脚本生成的,因为它更简单并且更易于维护。>我们已经简要介绍了PHP解释器在运行PHP代码时通过的四个阶段。这涉及使用各种扩展(包括令牌,PHP-ast,opcache和vld)来操纵和查看每个阶段的输出。
。>我希望本文能够帮助您对PHP的解释器有更好的整体理解,并显示了Opcache扩展的重要性(用于其缓存和优化能力)。
经常询问有关PHP执行过程的问题(常见问题解答)>
PHP在执行过程中如何处理错误?php扩展是在PHP语言中添加新功能和功能的模块。在执行过程中,它们被加载到PHP运行时环境中,可用于执行从数据库访问到图像处理的广泛任务。 PHP扩展名为C编写,并编译为机器代码,这使其非常快速有效。它们是PHP生态系统的关键组成部分,并有助于其灵活性和功率。
>>
PHP在执行过程中如何处理内存管理? PHP具有内置内存管理器,可以在执行过程中处理内存分配和Deallocation。内存管理器根据需要为变量和数据结构分配内存,并在不再需要内存时对内存进行交易。 PHP还具有一个垃圾收集器,该垃圾收集器会自动释放不再使用的内存。这有助于防止内存泄漏并将内存使用控制在控制之下。> Web服务器在PHP执行过程中的作用是什么?>
> Web服务器在PHP执行中起关键作用过程。它负责处理HTTP请求,对这些请求运行PHP脚本,然后将HTTP响应发送回客户端。 Web服务器与PHP解释器和PHP引擎紧密合作,以执行PHP脚本并生成动态网页。 PHP最常用的Web服务器是Apache和Nginx。 MySQL,PostgreSQL和SQLite。它在执行过程中使用数据库特异性扩展与这些数据库进行交互。这些扩展提供了一组功能,可用于连接到数据库,执行SQL查询,获取结果并处理错误。 PHP还支持PDO(PHP数据对象)扩展名,该扩展提供了数据库交互的数据库-Nostic接口。PHP对会话管理具有内置支持,这使其可以在不同的HTTP请求之间维护状态。启动会话后,PHP会创建唯一的会话ID,并将其存储在客户端浏览器上的cookie中。然后,此会话ID通过每个后续请求发送回服务器,允许PHP识别客户端并检索相应的会话数据。 PHP的会话管理功能使在Web应用程序中实现用户身份验证,购物车和其他状态功能变得易于实现。
以上是PHP如何执行 - 从源代码到渲染的详细内容。更多信息请关注PHP中文网其他相关文章!