Is it possible to show how php is calculating the solution to a problem.
For example:
<?php
$equation = (5+1)*3/9; // outputs 2
?>
If would like to see all the steps it processed to come to that solution: IE:
(5+1) = 6
6*3 = 18
18/9 = 2
The short answer is "maybe". It's not possible to hook into PHP internals during runtime like you would have expected it. But, there is an alternative which comes close to it using an external parser.
The reason for this is, that PHP uses an abstract syntax tree (AST) internally to define the processing steps as well as to optimize execution by creating a better binary representation as OpCache in order to avoid parsing and processing the same scripts again and again.
Thus, in case you need to know more about the processing in PHP, you'd consider analyzing the PHP C source code:
ZEND_ADD
, ZEND_SUB
, ZEND_MUL
, ZEND_DIV
add_function
, sub_function
, mul_function
, div_function
nikic/php-parser
A re-implementation of the AST parser in PHP is available as well, see https://github.com/nikic/PHP-Parser.
The following example puts the expression $equation = (5+1)*3/9; // outputs 2
of the original question to a dedicated math.php
file. The parser is executed using the following CLI commands:
composer require nikic/php-parser
vendor/bin/php-parse math.php
Which will output the parsed syntax tree of $equation = (5+1)*3/9; // outputs 2
(which is basically the answer to the original question):
====> 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
)
)
)
By reading https://nikic.github.io/2017/04/14/PHP-7-Virtual-machine.html (by the author of the mentioned PHP AST parser above) one might find some more information about analyzing PHP processing. However, this section does not give additional answers to the question - it's more to outline alternatives and what they actually reveal.
php -d opcache.enable_cli=1 -d opcache.opt_debug_level=0x10000 math.php
The command above executed in a CLI context enables OpCache debugging and outputs the following:
$_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)
The debug output above just contains the result int(2)
but not the according steps that have been determined for the syntax tree - which is quite obvious since they are not required for an optimized version.
This can be verified by looking into the generated OpCache binary as well:
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
(my working directory is /var/www/developer/
which has a sub-directory opcache/
)
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...|
The above hexdump just shows the end of the OpCache file. The first byte in the marked line (at 0x00000250
) contains the optimized result 02
already. For the given example, there are no further pointers to operators (e.g. ZEND_MUL
) nor the integer literals 5
, 1
, 3
or 9
. Thus, the result of the constant equation is directly stored in OpCache already.