PHP_FUNCTION(gettype)
{
zval *arg;
zend_string *type;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ZVAL(arg)
ZEND_PARSE_PARAMETERS_END();
type = zend_zval_get_legacy_type(arg);
if (EXPECTED(type)) {
RETURN_INTERNED_STR(type);
} else {
RETURN_STRING("unknown type");
}
}
mixed
string
string
function gettype(mixed $value) {}
PHP itself: "arginfo" structures are generated for reflection information
3rd party tooling: e.g. static analysers
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gettype, 0, 1, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0)
ZEND_END_ARG_INFO()
Internal function parameter validation (ZPP) used to be largely inconsistent
// Parameter count validation was forgotten:
get_defined_vars(null);
// Nothing happens
// The first parameter was always parsed weakly,
// regardless of strict_types mode
printf([]);
// array
// The second parameter was always parsed strictly,
// regardless of strict_types mode
chown("/temp/foo.txt", false);
// Warning: Parameter 2 should be string or int
// Parameter validation was omitted when the DOM
// extension is not enabled
(new XmlReader())->expand("wrong parameter");
// Warning: DOM support is not enabled
Now, only a few dozens of parameters with weird types don't behave in a standard way:
450+ internal functions didn't have proper default value handling
var_dump(substr("abc", 0));
var_dump(substr("abc", 0, null));
var_dump(getenv("ENV_VAR"));
var_dump(getenv());
var_dump(getenv(null));
Now, there are only 63 functions left, mainly with overloaded signatures:
rand(); // works
rand(0, 100); // works
rand(10); // doesn't work
Reflection info for default values of internal functions was not available
class MyDateTimeZone extends DateTimeZone
{
public static function listIdentifiers()
{
}
}
// PHP 7.4:
// Declaration of MyDateTimeZone::listIdentifiers() should be compatible with
// DateTimeZone::listIdentifiers($what = NULL, $country = NULL)
// PHP 8.0:
// Declaration of MyDateTimeZone::listIdentifiers() must be compatible with
// DateTimeZone::listIdentifiers(int $timezoneGroup = DateTimeZone::ALL,
// ?string $countryCode = null)
<?php
function array_walk(array|object &$input, callable $funcname, mixed $userdata): bool {}
function array_walk(array|object &$input, callable $callback, mixed $argument): bool {}
class DomNode
{
public function C14NFile(
string $uri, bool $exclusive = false, bool $with_comments = false,
?array $xpath = null, ?array $ns_prefixes = null,
) {}
public function C14NFile(
string $uri, bool $exclusive = false, bool $withComments = false,
?array $xpath = null, ?array $nsPrefixes = null,
) {}
}
function openssl_x509_check_private_key(OpenSSLCertificate|string $x509, $key): bool {}
function openssl_x509_check_private_key(OpenSSLCertificate|string $certificate, $private_key): bool {}
All the parameter names are currently being reviewed
count(null);
// PHP 7.4:
// count(): Parameter must be an array or an object that implements Countable
// PHP 8.0:
// count(): Argument #1 ($var) must be of type Countable|array, null given
version_compare("7.4.0", "8.0.0.", "?");
// PHP 7.4:
// null
// PHP 8.0:
// version_compare(): Argument #3 ($operator) must be a valid comparison operator
700+ warnings were reclassified as an exception
There are only 13 extensions which still define resources
Hundreds of error messages were improved
<?php
rand([], 1);
foo();
// PHP 7.4:
// rand() expects parameter 1 to be int, array given
// Argument 1 passed to foo() must be of the type int, array given
// PHP 8.0:
// rand(): Argument #1 ($min) must be of type int, array given
// foo(): Argument #1 ($i) must be of type int, array given
foreach(null as $i) {}
// PHP 7.4:
// Warning: Invalid argument supplied for foreach()
// PHP 8.0:
// Warning: foreach() argument must be of type array|object, null given
count([], 2);
// PHP 7.4:
// 0 is returned, the $mode parameter is ignored
// PHP 8.0:
// count(): Argument #2 ($mode) must be either COUNT_NORMAL or COUNT_RECURSIVE