====== PHP RFC: var_info ====== * Version: 1.0 * Date: 2016-06-26 * Author: Richard Fussenegger * Status: Declined * First Published at: http://wiki.php.net/rfc/var_info ===== Introduction ===== Debug, error, and exception messages in PHP often contain type information about variables that did not satisfy a defined validation constraint. The idiomatic way to add this type information is currently via the ''[[https://secure.php.net/gettype|gettype()]]'' function, however, the information that can be retrieved via that function is very sparse and developers need to repeat certain patterns over and over again to enrich it. This RFC proposes a new function called ''var_info()'' that addresses this issue and helps developers to create better debug, error, and exception messages in their software. ===== Proposal ===== Research of big and successful PHP userland projects (e.g. a search with ''is_object\([^\)]+\)\s*\?\s*get_class\([^\)]+\)\s*:\s*gettype'' shows 44 results in a fresh Drupal 8.2.x checkout with all composer dependencies installed) has shown that the ''gettype()'' function is often used as follows: $type = is_object($var) ? get_class($var) : gettype($var); The result of such a check is then mostly used as part of an error message. It is trivial to write the above line of code, and the performance hit of an additional function call is negligible (due to the fact that it is usually only executed in error branches of software). Nevertheless, it is an unnecessary hurdle, and the so retrieved information on the type is not very extensive. Hence, the proposal for a new function that is called ''var_info()'' that works as follows: echo var_info([]); // array echo var_info([SomeClass::class, 'someMethod']); // callable array echo var_info([new SomeClass, 'someMethod']); // callable array echo var_info(false); // false echo var_info(-1.0); // negative float echo var_info(0.0); // zero float echo var_info(1.0); // positive float echo var_info(INF); // infinite float echo var_info(NAN); // invalid float echo var_info(-1); // negative int echo var_info(0); // zero int echo var_info(1); // positive int echo var_info(new stdClass); // object of class stdClass echo var_info(new Some\Namespaced\UserClass); // object of class Some\Namespaced\UserClass echo var_info(unserialize('O:1:"A":0:{}')); // object of class __PHP_Incomplete_Class echo var_info(function () {}); // object of class Closure echo var_info(STDIN); // resource of type stream $fh = tmpfile(); fclose($fh); echo var_info($fh); // closed resource echo var_info('string'); // string echo var_info('strlen'); // callable string echo var_info('SomeClass::someMethod'); // callable string echo var_info('10'); // numeric string echo var_info('1.0'); // numeric string echo var_info(true); // true The following table summarizes the possible return values in a more readable form: ^ Return Value ^ Comment ^ | ''array'' | | | ''callable array'' | ''[[https://secure.php.net/is_callable|is_callable()]]'' | | ''false'' | ''bool(false)'' | | ''negative float'' | ''$var < 0.0'' | | ''zero float'' | ''$var === 0.0 || $var === -0.0'' | | ''positive float'' | ''$var > 0.0'' | | ''infinite float'' | ''[[https://secure.php.net/is_infinite|is_infinite()]]'' | | ''invalid float'' | ''[[https://secure.php.net/is_nan|is_nan()]]'' | | ''negative int'' | ''$var < 0'' | | ''zero int'' | ''$var === 0 || $var === -0'' | | ''positive int'' | ''$var > 0'' | | ''object of class %s'' | ''%s'' will contain the result of ''[[https://secure.php.net/get_class|get_class()]]''. | | ''resource of type %s'' | ''%s'' will contain the result of ''[[https://secure.php.net/get_resource_type|get_resource_type()]]''. | | ''closed resource'' | If no type is available anymore or is invalid/unknown. | | ''string'' | | | ''callable string'' | ''[[https://secure.php.net/is_callable|is_callable()]]'' | | ''numeric string'' | ''[[https://secure.php.net/is_numeric|is_numeric()]]'' | | ''true'' | ''bool(true)'' | The return values do not contain any kind of special characters like brackets in order to not interfere with the formatting a developer might choose to format her message (e.g. //(// and //)// are not appropriate within //(// and //)// in English language). This should be taken into account in possible future extensions of this function. Developers should however not rely on the returned values for anything other than outputting them. This is because the returned values might change in any major PHP release, the PHP team will of course take careful care not to alter the output during non-major releases, but it is still highly discouraged. ==== Prefix Choice ==== The function prefix ''var_'' was chosen on purpose because another possibly more suitable prefix like ''val_'' or ''value_'' would introduce a new prefix to the PHP ecosystem. It is true that this function can be used with the return value of functions too as well as with literal values, however, exactly the same argument is true for ''var_dump()'' and ''var_export()''. Naming consistency is very important and this tiny blemish is on purpose in this case. ==== Core Inclusion ==== Writing a function that does exactly the same as the proposed ''var_info()'' function in userland is trivial. However, the inclusion of tiny dependencies for every day tasks is not something library developers want since every dependency results in an maintainability increase. Another solution would be to copy the few lines of code that provide the functionality from project to project, it should be obvious that this is never an appropriate solution for any kind of problem. Hence, such a tiny but portable functionality is best provided by the platform itself. The inclusion in core should support developers while creating useful error messages, in tiny scripts as well as fully fledged applications and replace calls to ''gettype()'' for that purpose or even ''var_dump()''/''var_export()''. ===== Backward Incompatible Changes ===== None ===== Proposed PHP Version(s) ===== This RFC targets the next feature release, currently 7.1.0. ===== RFC Impact ===== ==== To SAPIs ==== None ==== To Existing Extensions ==== None ==== To Opcache ==== None ==== New Constants ==== None ==== php.ini Defaults ==== None ===== Open Issues ===== * Whether to output ''negative zero float'' for ''-0.0'' values or not. * Whether to output ''invalid object'' instead of ''object of class __PHP_Incomplete_Class''. ===== Unaffected PHP Functionality ===== Everything ===== Future Scope ===== None ===== Proposed Voting Choices ===== This RFC will have a single poll that requires a 50%+1 majority. * Yes * No ===== Patches and Tests ===== The [[https://github.com/php/php-src/pull/1957|GitHub Pull Request #1957]] contains the implementation as well as tests for the new function. The changes in the PR are considered final, however, a thorough code review would be much appreciated and might result in minor changes. ===== References ===== * [[http://news.php.net/php.internals/94262|php-internals thread]] for this RFC. * [[http://news.php.net/php.internals/93762|php-internals thread]] for the initial proposal as extended mode of ''typeof()''. ===== Rejected Features ===== None