ホームページ > バックエンド開発 > PHPチュートリアル > PHP: PHP に関数強制型復帰を追加

PHP: PHP に関数強制型復帰を追加

WBOY
リリース: 2016-06-23 13:10:59
オリジナル
1144 人が閲覧しました

開発プロセスでは、関数の戻り値の型を決定して変更する必要がありますが、PHP は型付けが弱い言語であるため、このような構文検証が行われず、多くの落とし穴が発生しました。

たとえば、次のコード:

<?phpfunction getArticles(...){    $arrData = array();    if($exp1){      return $arrData;    }else if($exp2){      return 1;    }else{      return false;    }}$arrData =getArticles(...);foreach($arrData as $record){//do something.....}?>
ログイン後にコピー

getArticles 関数は、bool、int、配列など、さまざまな条件に従ってさまざまなタイプの値を返します。通常、このタイプの関数は配列を返し、それを使用します。しかし、関数の戻り値の型が固定されていないため、呼び出し時にさまざまな思わぬ落とし穴が発生する可能性があり、標準化できないので、それを強制的に実行する必要があると考えました。

関数/メソッドの戻り値の型を強制できます:

int function a(){    ......    return 1;}bool function b(){    ......    return false;}array function c(){    ......    return array();}object function d(){    ......    return new a();}
ログイン後にコピー

4 つの必須の型制限をサポートします: int、array、bool、object 戻り値が関数宣言の型と一致しない場合、警告がスローされます。本来はエラーをスローする予定でしたが、これは厳しすぎてエラーではなく例外としか考えられないので、警告を使用します。

PHP 自体は int 関数のような構文をサポートしていないため、それをサポートしたい場合は、まず構文パーサーを修正する必要があります。詳しくは説明しません。詳細はこちらを参照してください。最初に構文を変更します。Zend/zend_ language_scanner.l ファイルをスキャンします。

次のコードを追加します。

<ST_IN_SCRIPTING>"int" {    return T_FUNCTION_RETURN_INT;}<ST_IN_SCRIPTING>"bool" {    return T_FUNCTION_RETURN_OBJECT;}<ST_IN_SCRIPTING>"object" {    return T_FUNCTION_RETURN_OBJECT;}<ST_IN_SCRIPTING>"resource" {    return T_FUNCTION_RETURN_RESOURCE;}
ログイン後にコピー

スキャナがキーワード int、bool、object、resource、array をスキャンするときの意味は非常に簡単です。対応する T_FUNCTION_* を返します。これは、トークンが異なると異なる方法で処理されるため、最初に Zend/zend_ language_parser.y ファイルに定義する必要があります

..........%token T_FUNCTION_RETURN_INT%token T_FUNCTION_RETURN_BOOL%token T_FUNCTION_RETURN_STRING%token T_FUNCTION_RETURN_OBJECT%token T_FUNCTION_RETURN_RESOURCE1然后增加token处理逻辑:1function:        T_FUNCTION { \(.u.opline_num = CG(zend_lineno);\).u.EA.var  = 0; }    |   T_FUNCTION_RETURN_INT T_FUNCTION {            \(.u.opline_num = CG(zend_lineno);            \).u.EA.var = IS_LONG;    }    |   T_FUNCTION_RETURN_BOOL T_FUNCTION {            \(.u.opline_num = CG(zend_lineno);            \).u.EA.var = IS_BOOL;    }    |   T_FUNCTION_RETURN_STRING T_FUNCTION {            \(.u.opline_num = CG(zend_lineno);            \).u.EA.var = IS_STRING;    }    |   T_FUNCTION_RETURN_OBJECT T_FUNCTION {            \(.u.opline_num = CG(zend_lineno);            \).u.EA.var = IS_OBJECT;    }    |   T_FUNCTION_RETURN_RESOURCE T_FUNCTION {            \(.u.opline_num = CG(zend_lineno);            \).u.EA.var = IS_RESOURCE;    }    |   T_ARRAY T_FUNCTION {            \(.u.opline_num = CG(zend_lineno);            \).u.EA.var = IS_ARRAY;    }
ログイン後にコピー

$$.u.EA。 var は関数の戻り値の型を格納し、最終的にそれを使用して戻り値を追跡します。構文インタープリターが新しい PHP 構文を処理できるように、値の型が一致します。これだけでは十分ではなく、関数宣言定義の処理ロジックも変更する必要があります Zend/zend_compile.c:: zend_do_begin_function_declaration

......zend_op_array op_array;char *name = function_name->u.constant.value.str.val;int name_len = function_name->u.constant.value.str.len;int function_type = function_token->u.EA.var; //保存函数类型,在语法解释器中增加的int function_begin_line = function_token->u.opline_num;......op_array.function_name = name;op_array.fn_type = function_type; //将类型保存到op_array中,op_array.return_reference = return_reference;op_array.fn_flags |= fn_flags;op_array.pass_rest_by_reference = 0;..........
ログイン後にコピー

PHP はまず PHP 構文を解析して対応するオペコードを生成し、必要な環境とパラメーター情報をexecute_data グローバル変数、そして最後に、オペコードは実行関数を通じて 1 つずつ実行されるため、処理を行うには、オペコードに関数タイプを保存する必要があります。 op_array の構造を変更し、zend_uint fn_type を追加します。最後に、関数を破棄すると、トークン T_RETURN が生成され、戻り値の型に応じてさまざまなコールバック関数が呼び出されます。戻り値が const 型データの場合、ZEND_RETURN_SPEC_CONST_HANDLER の戻り値は一時データ (return 1 など)、ZEND_RETURN_SPEC_TMP_HANDLER 戻り値は変数 (return $a、ZEND_RETURN_SPEC_VAR_HANDLER など) です。これら 3 つのコールバック関数に処理ロジックを追加する必要があります。

コールバック関数 return の前に次のコードを追加します。

ZEND_RETURN_SPEC_CONST_HANDLERZEND_RETURN_SPEC_TMP_HANDLERZEND_RETURN_SPEC_VAR_HANDLER
ログイン後にコピー
fn_type が戻り値の型と比較され、一致しない場合は、この警告がスローされます。すでにパッチを適用していますが、現在は php5.3 バージョンのみをサポートしています。必要に応じて試してください。なぜこの構文が正式にサポートされていないのかはわかりませんが、かなり必要だと思います。

パッチをダウンロードします: php-syntax.patch

続き: その後、私はバード兄弟と話しましたが、彼の答えは次のとおりです: 「このトピックは基本的にメールグループの生理的な投稿です... 1. PHP は型であるため, 多くの型は相互に変換できるので、暗黙的な変換が必要ですか? 変換にさまざまな変換ルールが含まれる場合、これは制限されすぎます。十分ではありません (さまざまなカスタム クラスと継承クラス) 3. 将来的に JIT を実行したい場合は、サポートすることを検討してください。」 この観点からすると、公式もこの問題にかなり巻き込まれています。変換を強制するのではなく、警告をスローして、変換するかどうかを開発者に決定させる方が良いでしょうか?
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート