是否可以显示php如何计算问题的解决方案。
例如:

<?php
$equation = (5+1)*3/9; // outputs 2
?>

如果希望查看它处理的所有步骤以获得该解决方案:
IE:
(5+1)=6
6×3=18
18/9=2

最佳答案

简短的回答是“也许”。在运行时不可能像预期的那样钩住php内部。但是,有一种替代方法可以使用外部解析器接近它。
php脚本解析器&抽象语法树(ast)
原因是,php在内部使用抽象语法树(ast)来定义处理步骤,并通过创建更好的二进制表示形式opcache来优化执行,以避免一次又一次地解析和处理相同的脚本。
因此,如果您需要更多地了解php中的处理,可以考虑分析php c源代码:
AST基础:https://github.com/php/php-src/blob/856b63a632c90c0c23ac49b8e51d5e0b45cb0c4a/Zend/zend_ast.c
例如,搜索ast文本,如ZEND_ADDZEND_SUBZEND_MULZEND_DIVadd_function
操作员执行:https://github.com/php/php-src/blob/856b63a632c90c0c23ac49b8e51d5e0b45cb0c4a/Zend/zend_operators.c
例如,搜索sub_functionmul_functiondiv_functionnikic/php-parser$equation = (5+1)*3/9; // outputs 2
php脚本中的ast-math.php
还可以使用php重新实现ast解析器,请参见https://github.com/nikic/PHP-Parser
下面的示例将原始问题的表达式$equation = (5+1)*3/9; // outputs 2放入专用的int(2)文件。解析器使用以下cli命令执行:

composer require nikic/php-parser
vendor/bin/php-parse math.php

它将输出/var/www/developer/的解析语法树(基本上是对原始问题的回答):
====> File math.php:
==> Node dump:
array(
    0: Stmt_Expression(
        expr: Expr_Assign(
            var: Expr_Variable(
                name: equation
            )
            expr: Expr_BinaryOp_Div(
                left: Expr_BinaryOp_Mul(
                    left: Expr_BinaryOp_Plus(
                        left: Scalar_LNumber(
                            value: 5
                        )
                        right: Scalar_LNumber(
                            value: 1
                        )
                    )
                    right: Scalar_LNumber(
                        value: 3
                    )
                )
                right: Scalar_LNumber(
                    value: 9
                )
            )
        )
    )
    1: Stmt_Nop(
        comments: array(
            0: // outputs 2
        )
    )
)

Opcache分析
通过阅读https://nikic.github.io/2017/04/14/PHP-7-Virtual-machine.html(由上面提到的php ast解析器的作者编写)可以找到有关分析php处理的更多信息。然而,这一部分并没有给出这个问题的额外答案——它更多的是概述备选方案以及它们实际揭示的内容。
php -d opcache.enable_cli=1 -d opcache.opt_debug_level=0x10000 math.php

上面在cli上下文中执行的命令启用opcache调试并输出以下内容:
$_main: ; (lines=3, args=0, vars=1, tmps=1)
    ; (before optimizer)
    ; /var/www/developer/math.php:1-4
L0:     EXT_STMT
L1:     ASSIGN CV0($equation) int(2)
L2:     RETURN int(1)

上面的调试输出只包含结果opcache/而不包含为语法树确定的相应步骤,这一点非常明显,因为优化版本不需要这些步骤。
这可以通过查看生成的opCax二进制文件来验证:
php -d opcache.enable_cli=1 -d opcache.opt_debug_level=0x10000 \
  -d opcache.file_cache=/var/www/developer/opcache/ \
  -d opcache.file_cache_only=1 math.php
hexdump opcache/08202de11af2c60edca0b5438eeefab6/var/www/developer/math.php.bin -C

(我的工作目录是0x00000250,它有一个子目录02
00000210  2f 76 61 72 2f 77 77 77  2f 64 65 76 65 6c 6f 70  |/var/www/develop|
00000220  65 72 2f 6d 61 74 68 2e  70 68 70 00 75 7f 00 00  |er/math.php.u...|
00000230  28 32 60 aa 75 7f 00 00  30 32 60 aa 75 7f 00 00  |(2`.u...02`.u...|
00000240  38 32 60 aa 75 7f 00 00  40 32 60 aa 75 7f 00 00  |82`.u...@2`.u...|
00000250  02 00 00 00 00 00 00 00  04 00 00 00 ff ff ff ff  |................| <--
00000260  01 00 00 00 00 00 00 00  04 00 00 00 ff ff ff ff  |................|
00000270  e9 0b 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000280  00 00 00 00 00 00 00 00  02 00 00 00 65 08 08 08  |............e...|
00000290  e9 0b 00 00 00 00 00 00  50 00 00 00 00 00 00 00  |........P.......|
000002a0  00 00 00 00 00 00 00 00  02 00 00 00 26 10 01 08  |............&...|
000002b0  e9 0b 00 00 00 00 00 00  10 00 00 00 00 00 00 00  |................|
000002c0  00 00 00 00 ff ff ff ff  04 00 00 00 3e 01 08 08  |............>...|
000002d0  88 02 00 00 00 00 00 00  00 00 00 00 06 02 00 00  |................|
000002e0  cb 5b 29 c4 00 e7 1a 80  08 00 00 00 00 00 00 00  |.[).............|
000002f0  65 71 75 61 74 69 6f 6e  00 32 60 aa 75 7f 00 00  |equation.2`.u...|

上面的hexdump只显示了opcache文件的结尾。标记行中的第一个字节(atZEND_MUL)已包含优化结果5。对于给定的示例,没有指向运算符(例如1)的进一步指针,也没有指向整数文本39、或。因此,常数方程的结果已经直接存储在opcache中。

10-04 22:23
查看更多