Php: add a function forced type to php to return

Source: Internet
Author: User
Php: add a function to php to force the type to be returned. during the development process, the type of the return value of the function should be fixed, but PHP is a weak language, therefore, PHP does not have such syntax verification, which causes many pitfalls.

For example, the following code:

 

The getArticles function returns different types of values based on different conditions, including bool, int, and array. Normally, such functions want to return an array and then take the array for some other operations, however, because the type of the function return value is not fixed, various unexpected pitfalls may occur during the call. Therefore, I thought that since it cannot be standardized, it should be enforced directly.

Function/method return values can be forced type:

int function a(){    ......    return 1;}bool function b(){    ......    return false;}array function c(){    ......    return array();}object function d(){    ......    return new a();}

Four types of mandatory restrictions are supported: int, array, bool, and object. when the returned value does not match the type in the function declaration, the system throws a warning command to throw an error, but it is too embarrassing, it can only be regarded as an exception, not an error, so we should use warning.

PHP itself does not support syntax such as int function. to support it, you must first set the syntax Parser. For more information about the syntax parser, see here.> View details, modify the syntax to scan the Zend/zend_language_scanner.l file.

Add the following code:

 
  "int" {    return T_FUNCTION_RETURN_INT;}
  
   "bool" {    return T_FUNCTION_RETURN_OBJECT;}
   
    "object" {    return T_FUNCTION_RETURN_OBJECT;}
    
     "resource" {    return T_FUNCTION_RETURN_RESOURCE;}
    
   
  
 

The scanner returns the corresponding T_FUNCTION _ * when scanning the keywords int, bool, object, resource, and array. this is a token, and the token performs different processing based on different tokens, token must be defined in the Zend/zend_language_parser.y file first.

Add the following code:

.......... % Token T_FUNCTION_RETURN_INT % token T_FUNCTION_RETURN_BOOL % token T_FUNCTION_RETURN_STRING % token T_FUNCTION_RETURN_OBJECT % token handle and add token processing logic: 1 function: 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 stores the function return type, and finally matches it with the return value type, so that the syntax interpreter can process our new php syntax. This is not enough. you also need to modify the processing logic Zend/zend_compile.c: zend_do_begin_function_declaration defined by the 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; // Save the function type. int function_begin_line = function_token-> u added to the syntax interpreter. opline_num ;...... op_array.function_name = name; op_array.fn_type = function_type; // Save the type to op_array; types = return_reference; types | = fn_flags; types = 0 ;..........

PHP parses the PHP syntax to generate the corresponding opcode, saves the required environment and parameter information to the execute_data global variable, and finally executes the opcode one by one through the execute function, therefore, you need to save the function type to opcode: op_array.fn_type = function_type; op_array does not have fn_type. modify the op_array structure and add zend_uint fn_type; finally, modify the opcode destroy function. The return function generates token T_RETURN, and the T_RETURN function calls different calback functions based on the returned type:

ZEND_RETURN_SPEC_CONST_HANDLERZEND_RETURN_SPEC_TMP_HANDLERZEND_RETURN_SPEC_VAR_HANDLER

It has three callback. if the returned value is a const data type, ZEND_RETURN_SPEC_CONST_HANDLER returns temporary data. for example, if return 1 is returned, ZEND_RETURN_SPEC_TMP_HANDLER returns a variable, such as return $, then ZEND_RETURN_SPEC_VAR_HANDLER

Therefore, the processing logic must be added to the three callback functions:

Add the following code before the callback function return:

if((EG(active_op_array)->fn_type > 0) && Z_TYPE_P(retval_ptr) != EG(active_op_array)->fn_type){        php_error_docref0(NULL TSRMLS_DC,E_WARNING, "function name %s return a wrong type.", EG(active_op_array)->function_name );    }

Fn_type is used to compare with the type of the returned value. If no match is found, this warning will be thrown. I have installed a patch. Currently, only php5.3 is supported. if you need it, you can play it. I don't know why the official website does not support this syntax. I think it is quite necessary.

Download patch: php-syntax.patch

Continued: later, I talked to laruence. The following is his answer: "This topic is basically the subject of menstruation in the contact group .... 1. if PHP is a type and many types can be converted to each other, do you want to convert them implicitly? your implementation is not converted. this is too limited. if conversion involves various conversion rules. 2. it is not supported, but your implementation is definitely not enough (various custom classes, and inheritance classes ). 3. we may consider supporting jit later. "In this case, this issue is also quite officially Tangled. it is true that my idea is not to force a conversion. I just need to throw a warning and let the developers decide whether to switch, is it better?

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.