Допустимые символы в ключах массива php?


86

У меня есть ключи массива php, которые заполнены множеством странных символов.

Это разрешено? Есть ли какие-то ограничения на то, что я не могу использовать?


Ограничения:$a = (object) ['@km³' => 123]; error_log($a->@km³);
Bitterblue

Ответы:


90

Согласно инструкции :

Ключ может быть целым числом или строкой. Значение может быть любого типа.

Кроме того, произойдут следующие преобразования клавиш:

  • Строки, содержащие допустимые целые числа, будут преобразованы в целочисленный тип. Например, ключ «8» будет фактически сохранен под номером 8. С другой стороны, «08» не будет приведено, так как это недопустимое десятичное целое число.
  • Плавающие числа также приводятся к целым числам, что означает, что дробная часть будет усечена. Например, ключ 8.7 будет фактически сохранен под номером 8.
  • Булы также приводятся к целым числам, то есть ключ true будет фактически сохранен под 1, а ключ false под 0.
  • Null будет преобразован в пустую строку, т. Е. Ключ NULL будет фактически сохранен под "".
  • Массивы и объекты нельзя использовать в качестве ключей. Это приведет к предупреждению: Недопустимый тип смещения.

Снова мануал :

Строка - это последовательность символов, где символ - это то же самое, что и байт. Это означает, что PHP поддерживает только 256-символьный набор и, следовательно, не предлагает встроенной поддержки Unicode. См. Подробную информацию о типе строки.

Короче говоря, любая строка может быть ключом. А строка может содержать любые двоичные данные (до 2 ГБ). Следовательно, ключом могут быть любые двоичные данные (поскольку строка может быть любыми двоичными данными).

Некоторое случайное (допустимое) злоупотребление ключами массива:

$w = array(chr(0) => 'null byte?', chr(rand(0, 255)) => 'random byte?');
var_dump($w);

1
Чтобы уточнить, это не означает, что вы не можете использовать строки Unicode в качестве ключей массива. Фактически, любая двоичная строка работает нормально. Я считаю, что отсутствие поддержки Unicode в PHP меня раздражает, поскольку это не совсем так. :)
deceze

1
@deceze Unicode подпадает под категорию «любые двоичные данные» :) (хотя, судя по формулировке руководства, полагаю, что пояснения необходимы). И высказывание «не предлагает встроенной поддержки Unicode» - это правда. Ядро PHP не включает Unicode-версии strlen, substr и т. Д. Хотя «не предлагает встроенную обработку строк Unicode» может быть более подходящим вариантом.
Корбин

3
Конечно, ядро ​​не содержит никаких средств для управления строками Unicode. Но если вы не хотите манипулировать строками, PHP их прекрасно поддерживает. И действительно, расширение MB доступно практически для каждой установки PHP по умолчанию, так что различие между «поддержкой ядра» или нет в основном академическое. :)
deceze

1
@deceze, может быть, в их примечании должно быть написано «не изначально (см. расширение mb)» или что-то в этом роде. Но ты прав. Любая установка PHP с 2005 года по существу поддерживает Unicode, хотя я бы сказал, что поддержка Unicode в PHP (с расширениями) по-прежнему немного неприятна.
Корбин

@Corbin, почему вы называете это злоупотреблением, а не использованием ?
Pacerier 07

12

Ключ должен быть строкой или целым числом. Происходит несколько кастингов, но я думаю, что руководство хорошо объясняет:

Ключ может быть целым числом или строкой. Значение может быть любого типа.

Кроме того, произойдут следующие преобразования клавиш:

  • Строки, содержащие допустимые целые числа, будут преобразованы в целочисленный тип. Например, ключ «8» будет фактически сохранен под номером 8. С другой стороны, «08» не будет приведено, так как это недопустимое десятичное целое число.
  • Плавающие числа также приводятся к целым числам, что означает, что дробная часть будет усечена. Например, ключ 8.7 будет фактически сохранен под номером 8.
  • Булы также приводятся к целым числам, то есть ключ true будет фактически сохранен под 1, а ключ false под 0.
  • Null будет преобразован в пустую строку, т. Е. Ключ NULL будет фактически сохранен под "".
  • Массивы и объекты нельзя использовать в качестве ключей. Это приведет к предупреждению: Недопустимый тип смещения.

Типы ресурсов теперь могут быть преобразованы в целые числа (не уверен, что это новая функция), поэтому вы можете использовать, например, дескриптор файла или дескриптор curl в качестве ключа косвенно, преобразовав его в целое число и используя его в качестве ключа.
thomasrutter

10

Я нашел этот ответ в поисках дополнительной информации о моей проблеме. Я использовал строки с символами UTF-8 в них, которые не работали как ключи к массиву, который у меня был.

Что-то типа

$str = "R&D - Solution";
$arr = array( "R&D - Solution" => "Research" );
echo $arr[$str];  // did not work

Решением (небольшим или умным) для меня было сделать это ..

$str = md5("R&D - Solution");
$arr = array( md5("R&D - Solution") => "Research" );
echo $arr[$str];  // works!

2
Мне нравится md5 () для генерации ключей массива. Даже если на данном этапе это не совсем необходимо, все равно кажется безопаснее.
billynoah

1
md5 () идеально подходит для генерации простого текстового ключа из любой строки. Проблема не в безопасности. Еще хорошо, что он быстрый. Единственная проблема заключается в том, решат ли они отказаться от него, а затем исключить его, потому что теперь он не подходит для того, что было изначально разработано. Мы увидим.
Патанджали

2
Вы использовали старую версию PHP? Ваш первый пример отлично работает в PHP 7.1.
Elliot B.

6

Ключи массива PHP могут быть целыми или строковыми. Строки PHP - это байтовые массивы, то есть последовательности байтов. Других типов строк не существует, и в противном случае PHP не налагает каких-либо особых ограничений на строки ключей массива. Другими словами: пока это строка, все идет.


Я думаю, что неявное приведение строки к целочисленному ключу - важное различие, которое необходимо сделать, поскольку некоторые функции работают по-разному, независимо от того, является ли ключ целым или нет. например, вы можете использовать произвольные строковые числа только для того, чтобы обнаружить, что функция массива позже переиндексирует их с 0..n-1.
Мэтью

1
Согласен, но я думаю, что это на границе области охвата этого вопроса. :)
deceze

5

Все, что вы можете вставить в строку PHP, можно использовать в качестве ключа массива. Нет ограничений на разрешенные символы.

$a = array();

$x = 'long string of random garage';
echo $a[$x]; // this is ok

$x = array();
echo $a[$x]; // not ok

1

Если сложные ключи вызывают ошибку «неопределенный индекс», возможно, у вас просто проблема «обрезки».

Я сходил с ума, потому что сложный ключ выдавал ошибку «неопределенный индекс», и я подумал, может быть, это нарушение синтаксиса. Ключ массива, вызывающий ошибку, был построен из поля запроса базы данных MySQL, который я преобразовывал в ключ и использовал в новом массиве. Ключ выглядел так: pl_1DNKoiJKwotCqAycickBVhTyа вот как был построен код.

//new array created from database query
$new_array[$dbquery['fieldname']] = {some value};

//key value found in field of second array
$keyval = $array_two['fieldname'];

//this produced the "undefined index" error
echo $new_array[$keyval];

когда, на самом деле, $keyvalи $dbquery['fieldname']оказалось идеальным совпадением (визуально подтверждается отображением обоих в браузере). Тайна была решена простым использованием trimво втором выражении следующего вида: « $keyval = trim($array_two['fieldname']);После обрезки» php больше не жаловался.

Надеясь, что это избавит некоторых от некоторых неприятных моментов ...


0

У меня лично не было проблем с необычными символами в ключах массива. Что является законным, а что нет, плохо документировано, кроме как сказать, что ключ должен быть скаляром. Лучше всего просто попробовать и посмотреть.


Да, немного противоречиво, но это хорошо задокументировано.
Корбин

0

В дополнение ко всем ответам, поскольку они верны: вы можете использовать PSR, что они представляют собой своего рода правила между лучшими программистами для хорошего и стандартного стиля программирования.


0

В массиве php вы не можете использовать ключ: 2.3 или десятичные числа


-1

Закодируйте страницу php в ANSI «é» можно будет использовать (Cinéma не будет отображаться как Cinà © ma). В Notepad ++ просто используйте меню Encode => Convert ANSI и сохраните


2
(Этот пост не дает качественного ответа на вопрос. Измените свой ответ или просто опубликуйте его как комментарий к вопросу).
sɐunıɔ ןɐ qɐp

Вы можете объяснить это дальше? Что, если éего нет, что, если OP все-таки не использует Notepad ++?
Нико Хаасе
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.