プロジェクトにはメンバーの有効期限が切れているかどうかを比較する関数があり、同僚のコードをレビューしたところ、記述方法がかなり変であることがわかりましたが、オンライン上にバグはありませんでした。
実装はおおよそ次のとおりです:
リーリー2 つの時間を比較する必要がある場合、通常は Unix タイムスタンプに変換され、2 つの int 型の数値と比較されます。この実装では、具体的には時間を文字列として表現し、2 つの文字列に対して比較演算を実行します。
書くことはさておき、PHP の内部で比較がどのように行われるのか非常に興味があります。
早速、ソースコードから追跡を開始しましょう。
zend_ language_parse.y には次のような構文があります:
リーリー明らかに、ここでオペコードをコンパイルするために zend_do_binary_op が使用されます。
リーリーこの関数は特別な処理を行わず、単にオペコード、オペランド 1 およびオペランド 2 を保存するだけです。
オペコードに従って、対応する処理関数: ZEND_IS_SMALLER_SPEC_CONST_CONST_HANDLER にジャンプします。
リーリー2 つの zval の比較は、compare_function を使用して処理されることに注意してください。
リーリーこの記事のケースに従って、この関数はいくつかの状況を例示しています。詳細を確認するには、zendi_smart_strcmp と入力してください。 リーリー
「2014-05-01 00:00:00」は数値に変換できますか?まだ is_numeric_string の実装規則を確認する必要があります。
リーリー
コードは比較的長いですが、注意深く読めば、str を num に変換するルールは非常に明確です。この例では、「2014-05-01 00:00:00」を数値に変換できないことを直接決定する、allow_errors パラメーターに特に注意してください。
最終的に、「2014-04-17 00:00:00」<「2014-05-01 00:00:00」は実際に memcmp ブランチを介して実行されます。
memcmpなので、記事冒頭の書き方でも正しく動作するのは理解できなくもありません。
フォールトトレラント変換
例:
リーリー
これは、PHP の日付関数の内部実装です。date を呼び出すとき、2 番目のパラメーターが文字列に渡されると、効果は次のようになります:
リーリー
通知レベルのエラーが報告されましたが、「0-1-2」は依然として正常に 0 に変換されました