Skip to content

RFC: Counting of non-countable objects #2185

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ PHP 7.2 UPGRADE NOTES
'Multiple' => ['One header', 'Another header'],
'Multiline' = "FirstLine\r\n SecondLine",
];
. count() now raises a warning when an invalid parameter is passed.
Only arrays and objects implementing the Countable interface should be passed.

- XML:
. utf8_encode() and utf8_decode() have been moved to the Standard extension
Expand Down
18 changes: 18 additions & 0 deletions Zend/tests/generators/errors/count_error.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--TEST--
Generators can't be counted
--FILE--
<?php

function gen() { yield; }

$gen = gen();

try {
count($gen);
} catch (Exception $e) {
echo $e;
}

?>
--EXPECTF--
Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
26 changes: 26 additions & 0 deletions ext/date/tests/timezone_transitions_get_variation2.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -145,24 +145,32 @@ int(8)

Warning: timezone_transitions_get() expects parameter 2 to be integer, array given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- int indexed array --

Warning: timezone_transitions_get() expects parameter 2 to be integer, array given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- associative array --

Warning: timezone_transitions_get() expects parameter 2 to be integer, array given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- nested arrays --

Warning: timezone_transitions_get() expects parameter 2 to be integer, array given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- uppercase NULL --
Expand Down Expand Up @@ -193,48 +201,64 @@ int(8)

Warning: timezone_transitions_get() expects parameter 2 to be integer, string given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- empty string SQ --

Warning: timezone_transitions_get() expects parameter 2 to be integer, string given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- string DQ --

Warning: timezone_transitions_get() expects parameter 2 to be integer, string given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- string SQ --

Warning: timezone_transitions_get() expects parameter 2 to be integer, string given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- mixed case string --

Warning: timezone_transitions_get() expects parameter 2 to be integer, string given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- heredoc --

Warning: timezone_transitions_get() expects parameter 2 to be integer, string given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- instance of classWithToString --

Warning: timezone_transitions_get() expects parameter 2 to be integer, object given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- instance of classWithoutToString --

Warning: timezone_transitions_get() expects parameter 2 to be integer, object given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- undefined var --
Expand All @@ -249,5 +273,7 @@ int(8)

Warning: timezone_transitions_get() expects parameter 2 to be integer, resource given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)
===DONE===
26 changes: 26 additions & 0 deletions ext/date/tests/timezone_transitions_get_variation3.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -145,24 +145,32 @@ int(1)

Warning: timezone_transitions_get() expects parameter 3 to be integer, array given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- int indexed array --

Warning: timezone_transitions_get() expects parameter 3 to be integer, array given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- associative array --

Warning: timezone_transitions_get() expects parameter 3 to be integer, array given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- nested arrays --

Warning: timezone_transitions_get() expects parameter 3 to be integer, array given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- uppercase NULL --
Expand Down Expand Up @@ -193,48 +201,64 @@ int(1)

Warning: timezone_transitions_get() expects parameter 3 to be integer, string given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- empty string SQ --

Warning: timezone_transitions_get() expects parameter 3 to be integer, string given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- string DQ --

Warning: timezone_transitions_get() expects parameter 3 to be integer, string given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- string SQ --

Warning: timezone_transitions_get() expects parameter 3 to be integer, string given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- mixed case string --

Warning: timezone_transitions_get() expects parameter 3 to be integer, string given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- heredoc --

Warning: timezone_transitions_get() expects parameter 3 to be integer, string given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- instance of classWithToString --

Warning: timezone_transitions_get() expects parameter 3 to be integer, object given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- instance of classWithoutToString --

Warning: timezone_transitions_get() expects parameter 3 to be integer, object given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

-- undefined var --
Expand All @@ -249,5 +273,7 @@ int(1)

Warning: timezone_transitions_get() expects parameter 3 to be integer, resource given in %s on line %d
string(7) "boolean"

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)
===DONE===
7 changes: 7 additions & 0 deletions ext/standard/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,7 @@ PHP_FUNCTION(count)

switch (Z_TYPE_P(array)) {
case IS_NULL:
php_error_docref(NULL, E_WARNING, "Parameter must be an array or an object that implements Countable");
RETURN_LONG(0);
break;
case IS_ARRAY:
Expand Down Expand Up @@ -820,8 +821,14 @@ PHP_FUNCTION(count)
}
return;
}

/* If There's no handler and it doesn't implement Countable then add a warning */
php_error_docref(NULL, E_WARNING, "Parameter must be an array or an object that implements Countable");
RETURN_LONG(1);
break;
}
default:
php_error_docref(NULL, E_WARNING, "Parameter must be an array or an object that implements Countable");
RETURN_LONG(1);
break;
}
Expand Down
42 changes: 42 additions & 0 deletions ext/standard/tests/array/count_invalid.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
--TEST--
Only arrays and countable objects can be counted
--FILE--
<?php

$result = count(null);
var_dump($result);

$result = count("string");
var_dump($result);

$result = count(123);
var_dump($result);

$result = count(true);
var_dump($result);

$result = count(false);
var_dump($result);

$result = count((object) []);
var_dump($result);

?>
--EXPECTF--
Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(0)

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
int(1)
18 changes: 18 additions & 0 deletions ext/standard/tests/array/count_recursive.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,11 @@ closedir( $resource2 );
--EXPECTF--
*** Testing basic functionality of count() function ***
-- Testing NULL --

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
COUNT_NORMAL: should be 0, is 0

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
COUNT_RECURSIVE: should be 0, is 0
-- Testing arrays --
COUNT_NORMAL: should be 2, is 2
Expand All @@ -141,9 +145,15 @@ COUNT_RECURSIVE: should be 8, is 8
COUNT_NORMAL: should be 3, is 3
COUNT_RECURSIVE: should be 6, is 6
-- Testing strings --

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
COUNT_NORMAL: should be 1, is 1

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
COUNT_RECURSIVE: should be 1, is 1
-- Testing various types with no second argument --

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
COUNT_NORMAL: should be 1, is 1
COUNT_NORMAL: should be 2, is 2
-- Testing really cool arrays --
Expand Down Expand Up @@ -184,11 +194,19 @@ COUNT_NORMAL is 4
COUNT_RECURSIVE is 7

-- Testing count() on constants with no second argument --

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
COUNT_NORMAL: should be 1, is 1

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
COUNT_NORMAL: should be 1, is 1

-- Testing count() on NULL and Unset variables --

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
COUNT_NORMAL: should be 0, is 0

Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d
COUNT_NORMAL: should be 1, is 1
COUNT_NORMAL: should be 0, is 0

Expand Down
Loading