先祖代々のコードの問題を解決するためであり、友人グループからもやはりPHP5のサポートが必要だという声を聞いたので、頑張って取り組んでいます。このバージョンをこの期間中に解決する必要があります。互換性の問題、問題が予想よりはるかに難しいとは予想していませんでした。
開発中に発生した問題 (主に物理的な作業) を記録し、共有したい場合は、興味のある友人が フォーク
コピーすると、コードに慣れなくなります。 PR に送信します。
PHP7 では、関数またはメソッドは execute_data->call->fbc
構造体の zend_execute_data
で実行されますが、PHP5 では、対応するフィールドが関数を取得します。は関数を呼び出しますが、この 2 つの違いは比較的大きいです。
後で調べたところ、現在実行されている関数の情報は PHP5 の opline
zend_execute_data
にあることが分かりましたが、PHP5.4 の前後でロジックが異なるため、必要があります。別の方法で処理されます (幸いなことに、コンパイラがエラーを表示したフィールド)
#if PHP_VERSION_ID < 50400 #define OP1_FUNCTION_PTR(n) (&(n)->op1.u.constant) #else #define OP1_FUNCTION_PTR(n) ((n)->op1.zv) #endif
最初の呼び出しは解決されましたが、埋め込まれた呼び出しが opline
にないことが判明し、バージョンがは異なり、入手場所も異なり、同じでした。 上記のオプリンの判定バージョン番号は同じではないため、体力に頼るしかありません。
#if PHP_VERSION_ID < 50500 if (execute_data->fbc != NULL) { fbc = execute_data->fbc; } #else if (execute_data->call != NULL && execute_data->call->fbc != NULL) { fbc = execute_data->call->fbc; } #endif
最終的な関数情報の取得は多層判定です
zend_function *fbc; #if PHP_VERSION_ID < 70000 #if PHP_VERSION_ID < 50500 if (execute_data->fbc != NULL) { fbc = execute_data->fbc; } #else if (execute_data->call != NULL && execute_data->call->fbc != NULL) { fbc = execute_data->call->fbc; } #endif if (fbc == NULL) { fbc = get_function_from_opline(execute_data->opline); } #else if (execute_data->call != NULL && execute_data->call->func != NULL) { fbc = execute_data->call->fbc; } #endif
oplineから問い合わせられるのは関数名のみで、対応する関数ポインタをglobal function table
static zend_function *get_function_from_opline(zend_op *opline) { zend_function *fbc; zval *function_name = OP1_FUNCTION_PTR(opline); if (Z_STRVAL_P(function_name) == NULL) { return NULL; } if (zend_hash_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name) + 1, (void **)&fbc) == FAILURE) { return NULL; } return fbc; }
全体として、PHP5 の処理は PHP7 の処理よりもはるかに複雑ですが、これは PHP7 の方が優れた仕事をすることも示しています。
これらはここ数日間の開発作業です。私が遭遇していない実際のオンライン環境がたくさんあるかもしれません。興味があれば、このツールを使用して問題を解決することも、一緒に作業することもできます。この小さなツールを改善するために。
来週か再来週に、関数とメソッドのパラメータ出力をサポートするための watch 関数を追加します。主に Java の Arthas から類推します。私が最もよく使うのはトレース関数とウォッチ関数だからです。PHP はオンラインでログを直接変更したり追加したりできますが、これは結局標準化されておらず、リリース プロセスが遅すぎます。ウォッチ関数は次のとおりだと思います。必要に応じて、おそらく
$ ./bin/deliverer -w foo -n 3
は、監視中の foo
関数が 3 回の呼び出し後に終了し、deliver-request-id
とその入力パラメータを出力することを意味します。その後、deliver-request-id
に基づいて完全なコール スタックを表示できます。
これに興味がある場合は、スターを付けてください。https://github.com/zhoumengkang/deliverer
インストールと使用について質問がある場合は、私を追加してください。 WeChat zhoumengkang 前嫌がらせするには、パスワード:deliveryer
推奨学習:「PHP ビデオ チュートリアル 」