Skip to content

Instantly share code, notes, and snippets.

@ameenross
Last active January 2, 2024 16:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ameenross/e7f4dea8468d178464ca2f221ede72c0 to your computer and use it in GitHub Desktop.
Save ameenross/e7f4dea8468d178464ca2f221ede72c0 to your computer and use it in GitHub Desktop.
<?php
/**
* Some PHP frameworks are sensitive to non-fatal PHP errors (even notices).
* Those same frameworks are strict about other things, like typing, and only
* use strict comparisons. On the other hand, they use count() on scalars
* without doing a type check, and rely on the bogus return value of `1`.
* The PHP devs considered this legacy behavior of PHP's count (to return `1`
* for scalars) a problem, and relying on it a BUG. So in PHP 7.2, the function
* still returns the same values, but it now triggers an E_WARNING.
* Since those frameworks use count on scalars in various places, now PHP
* triggers a warning, the framework converts that warning into an exception,
* breaking your application.
*
* Sometimes upgrading the framework (to a version with PHP 7.2 compatibility)
* is not wanted, so here's a quick way to save yourself out of that situation.
* This function returns the exact same value as count(), even using count() for
* performance reasons, but it prevents the E_WARNING from occurring.
*
* Now you just need to find-and-replace whereever count() is called in your
* framework and change it to this function. Of course, if you plan on using
* this trick in production it would probably be better to maintain a fork of
* the framework instead of messing with files in your vendor/.
*
* @see https://wiki.php.net/rfc/counting_non_countables
**/
if (!function_exists('countNoWarn')) {
/**
* Userland count() replacement that does not trigger PHP warnings. Meant for PHP 7.2.
*
* Also works on PHP 8.0 and up, where a count on a scalar results in a FATAL!
*
* @param mixed $param
* @param int $mode
* @return int
*
* @see https://gist.github.com/ameenross/e7f4dea8468d178464ca2f221ede72c0
*/
function countNoWarn($param, $mode = COUNT_NORMAL)
{
/**
* @see http://php.net/manual/en/function.count.php
* Returns the number of elements in array_or_countable. When the parameter
* is neither an array nor an object with implemented Countable interface,
* 1 will be returned. There is one exception, if array_or_countable is
* NULL, 0 will be returned.
*/
if (is_null($param)) {
return 0;
} elseif (is_array($param) || $param instanceof Countable) {
return count($param, $mode);
} else {
return 1;
}
}
}
@ameenross
Copy link
Author

Environments that display warnings or convert them to more severe errors/exceptions would be affected, but this should just bring attention to a bug in the code.

https://wiki.php.net/rfc/counting_non_countables

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment