@Hint

PHP: нужно ли создавать массив перед его заполнением?

Нужно ли инициализировать массив перед добавлением в него элементов?

Раньше я всегда дотошно проверял наличие всех родительских ветвей массива, но в последнее время использую только один isset. Сейчас же задумался, стоит ли создавать родительские подмассивы или же сразу заносить конечный элемент (а php создаст все промежуточные звенья автоматически). Как делать правильно?

Чтение

Было:
echo isset($a['a']) && isset($a['a']['b']) && isset($a['a']['b']['c']) ? 'exists' : 'error';


Стало:
echo isset($a['a']['b']['c']) ? 'exists' : 'error';


Запись

Было:
if (!isset($_SESSION['voted']) || !is_array($_SESSION['voted']))
{
   $_SESSION['voted'] = array();
}
$_SESSION['voted'][$voteId] = time();


Стало:
$_SESSION['voted'][$voteId] = time();

Правильно ли в обоих случаях сокращать код?
  • Вопрос задан
  • 2815 просмотров
Решения вопроса 1
@Bruteo
ru2.php.net/manual/en/language.types.array.php
Документация явно говорит, что можно.

$arr[key] = value;
$arr[] = value;
// key may be an integer or string
// value may be any value of any type

//If $arr doesn't exist yet, it will be created, so this is also an alternative way to create an array
Ответ написан
Пригласить эксперта
Ответы на вопрос 7
xaker1
@xaker1
На самом высоком уровне могут появиться варнинги, тем не менее такой подход допустим.

Если существует $a['a']['b']['c'], то и $a['a']['b'] должен существовать по определению.
Так что проверка родительских ветвей в данном случае излишна.
Ответ написан
Комментировать
@kastigar
С isset абсалютно верно. Но я бы не стал называть это «чтение», т.к. isset — это специальная конструкция языка. Если вы попытаетесь спросить индекс не-массива, то:
unset($a);
echo $a['a']['b']['c']; // будет warning
echo $a['a']; // тоже будет warning
isset($a['a']['b']['c']); // не будет warning'а

С записью тоже есть нюансы. Если переменная (даже если это элемент массива) не установлена, то её можно неявно использовать как массив. Но если она установлена и не является массивом, то могут быть проблемы:
<?php
unset($a);
$a['a'] = 'a'; // это ок
$a['b'] = 1; // это ок
$a['a'][0] = 'b'; // перезапишет первый символ строки!!!
$a['b'][0] = 'b'; // будет notice, про обращение к скаляру, как к массиву
unset($a);
$a['a']['b']['c']['d'] = 'str'; // тоже ок
$с = new SomeClass;
$с[0] = 'c'; // Если класс имплементил ArrayAccess интерфейс, то вызовется метод offsetGet,
             // иначе Fatal error

Так что если не уверены, что содержится в переменной или элементе массива, то лучше явно проинициализируйте массив.
Ответ написан
Комментировать
@resurection
Нельзя isset-ом проверять т.к. для null-ового значения она возвращает false. См. доку:

$a = array ('test' => 1, 'hello' => NULL);

var_dump(isset($a['test'])); // TRUE
var_dump(isset($a['hello'])); // FALSE

Для проверки существования ключа массива необходимо использовать array_key_exists():

var_dump(array_key_exists('hello', $a)); // TRUE

ru.php.net/manual/en/function.isset.php
Ответ написан
Комментировать
WebSpider
@WebSpider
Считаю, что надо проверять в том случае, если вы не хотите перезаписать уже существующиее значение, т.е.

if (!isset($_SESSION['voted'][$voteId])) {
  // Ещё не голосовали, учитываем голос
  $_SESSION['voted'][$voteId] = time();
}

В остальных случаях проверка необязательна. Естественно, при этом если внутри используются какие-либо переменные — они должны проверяться отдельно на существование и на правильность типа. В данном случае надо убедиться, что существует переменная $voteId и имеет тип числа
Ответ написан
Комментировать
charon
@charon
я думаю, что достаточно проверять конечный элемент массива. А если вас что-то смущает — включите журнал ошибок РНР с максимальным уровнем логирования: если не будет даже предупреждений, то всё ок.
Ответ написан
Комментировать
Fastto
@Fastto
стоит самый сверх-высокий уровень — нотисов нет, можно пользоваться, версия 5.3.6, что будет дальше неизвестно.
Ответ написан
Комментировать
Может отрефакторить код и заменить массив на объект?
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы