2016-08-04 2 views
2

Как я могу реализовать логику литья ключей массива PHP в PHP? Одна наивная реализация может заключаться в следующем.Userland реализация литья ключей массива PHP

function castKey($key) { 
    $array = [$key => null]; 
    return key($array); 
} 

Однако, кажется, расточительно выделять избыточный массив. Я бы предпочел точно подражать логике каста. Конечно, было бы полезно увидеть и понять исходный код, но я не уверен, где его найти.

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

  • Целые числа хранятся дословно.
  • Строки хранятся в виде строк, если они не являются похожими на целое число. Я не знаю точно, как PHP определяет, что строка выглядит как целое; будь то просто ^\d+$ или что-то более сложное.
  • Булевы отлиты целыми числами.
  • Поплавки отлиты целыми числами.
+0

не плавает, как ключи массива становятся строками? – cHao

+0

См. Правила для ключей массива в примере: http://php.net/manual/en/language.types.array.php#example-99 Также исходный код является открытым исходным кодом и находится на github: https: // github.com/php/php-src – Rizier123

ответ

1

Не-оптимизированная версия логики PHP массив ключ литья можно найти здесь: https://github.com/php/php-src/blob/dbf63cb98d642236da9b9b5c751f0d4f8223c77f/Zend/zend_API.c#L1630

Логика для обнаружения числовой строки (насколько ключи массива обеспокоены) можно найти здесь: https://github.com/php/php-src/blob/16160386982a86e6ec7969c6c89707d38228f19e/Zend/zend_hash.c#L2442

так реализация программы пользователей будет выглядеть примерно так:

function castKey($key) { 
    if (is_int($key)) { 
     return $key; 
    } 
    if (is_string($key)) { 
     // Only keys of the form 0|-?[1-9][0-9]* in the 
     // supported integer range are converted. 
     $int = filter_var($key, FILTER_VALIDATE_INT); 
     if (false !== $int && '-0' !== $key) { 
      return $int; 
     } 
     return $key; 
    } 
    if (null === $key) { 
     return ""; 
    } 
    if (is_bool($key) || is_double($key)) { 
     return (int) $key; 
    } 
    if (is_resource($key)) { 
     $id = (int) $key; 
     trigger_error("Resource ID#$id used as offset, casting to integer ($id)"); 
     return $id; 
    } 
    throw new Exception('Illegal offset type'); 
} 
+0

Спасибо NikiC! Я бы не стал использовать 'FILTER_VALIDATE_INT'. Без вашей помощи я бы прибегал к регулярному выражению, которое, вероятно, было бы слабым решением, если бы PHP-представление о том, какие строки целые числа изменяются между версиями. Я бы также никогда не знал, что ресурсы были отлиты от целых чисел. –

+0

Как в стороне, из этой части источника все еще неясно, как строки передаются целому числу. Кроме того, что нужно для проверки '$ int> = 0'? –

+1

@QuolonelQuestions Вы правы, я не дважды проверял реализацию и думал, что отрицательные числа не будут преобразованы ^^ Я также связал источник проверки числовой строки. – NikiC