Cюрприз #2
pcd@cd-laptop:~$ php -a
php > error_reporting(E_ALL);// устанавливаем уровень ошибок,
php > $ar = array(); // создаем массив
php > var_dump($ar[1]); // обращаемся к несуществующему индексу
Notice: Undefined offset: 1 in php shell code on line 1//логично
NULL
php > $null = null;// создаем переменну инициализированную нулом
php > var_dump($null[1]);// обращаемся к нему как к массиву
NULL// ошибки нет, это уже не совсем логично, т.к.
php > var_dump( (array) $null ) ; // при преобразовании нула в массив
array(0) {
}// получается пустой массив без индекса 1.
//ну хотя можно как то объяснить, т.к. null это особый тип.
php > $false = false;// boolean переменная, инициализированная ложью
php > var_dump($false[1]);// обращение как к массиву при этом к несуществующиему индексу
NULL// а как объяснить это????
php > var_dump((array)$false);// смотрим как ложь приводится к массиву.
array(1) {
[0]=>
bool(false)
}// этого я не ожидал
// но тогда получается что ...
php > echo (array) false ? 'true' : 'false';
true // ну а это просто п***ц, сколько человек могло попасть так!
Ну и навскидку надуманный пример, похожий на правду.
cd@cd-laptop:~$ cat ex1.php
class ExampleDb
{
/**
* This function return list of users as array,
* empty array on failure
*/
public function findAll($testValue = true)
{
return (array ) $this->_fetch_all($testValue);
}
protected function _fetch_all($testValue = true )
{
$goodData = array(
0 => array(
'name' => 'vasya',
'pass' => 'oyamd5withsolt',
),
1 => array(
'name' => 'vasay',
'pass' => 'oyamd5withsolt2',
),
);
try
{
;//do smth
}
catch (Exception $e)
{
return false; //strange architector
}
$retValue = $testValue ? $goodData : false;
var_dump($retValue);
return $retValue;
}
}
$ob = new ExampleDb();
$users = $ob->findAll(false);// error happens !
//strange dev
if ( isset($users[0]) )
echo "You win! Your prize 10000k euros from dev salary!";
?>
cd@cd-laptop:~$ php ex1.php
(bool)false // мы видим что была ошибка
You win! Your prize 10000k euros from dev salary!cd@cd-laptop:~$
// но тем не менее кто то выйграл.
//Ну что теперь 10 лет работаем на еду?
4 comments:
Знатный косяк. Хотя явное приведение к массиву достаточно извращенное желание.
Баг-репорт засабмичен?
1. Это не баг, это вроде задокументированная вещь :)
Порылся в php.net
Преобразование в массив
Для любого из типов: integer, float, string, boolean и resource, если вы преобразуете значение в массив, вы получите массив с одним элементом (с индексом 0), являющимся скалярным значением, с которого вы начали.
Просто по моему мнению, в php слишком много вещей которые нужно знать, а у меня память плохая :) Поэтому я узнав язык пытаюсь пользоваться "ожидаемыми" вещами, разумеется проверяя их.
А вот прикол с явным приведением к массиву вылез у нас в проекте :)
классическая проблема с scalar -> array выглядит примерно так:
function getSomeArray() {
if (something) {
return array(1,2,3);
} else {
return null;
}
}
//...
if (count($arr = getSomeArray())) {
echo 'non-empty array' . var_export($arr, true);
}
Не спорю, это все правильно.
Однако что делать с
php > var_dump( count(false) ) ;
int(1)
php > var_dump( count(null) ) ;
int(0)
php > var_dump( count(array() ) ) ;
int(0)
Суть в следующем, очень часто функция в качестве ошибки возвращает именно false. Правильнее конечно проверять возвращаемое значение как
if ( false !== funcGetArray() )
{
// do smth
}
Однако про это часто забывается, а в приведенном примере
if ( count ( $ar = functGetArray() ) )
// do ok
else
// do error
Если функция вернет false, то мы все равно в луже.
Post a Comment