PHP: Cannot determine default value for internal functions

09 Oct 2014

Зашла речь про небезызвестный htmlspecialchars, но не просто у нем, а о нем и о работе с htmlentities. Если передать в этот метод строку с этими энтитями, то получим двойное перекодирование.

echo htmlspecialchars('"текст"');
"текст"

Именно для того, чтобы избежать подобного был добавлен параметр double_encode, который по дефолту всегда true.

Но речь не об этом.

Речь о том, что до этого параметра в спецификации стоит еще два других с дефолтными значениями.

На ум приходит использовать рефлексию для получения дефолтных значений и передачи их в функцию. Но не все так просто.

Сначала напишем код, который будет вызывать функции принимая в качестве параметра ассоциативный массив с онными.

function call\_user\_func\_params(callable $func, array $params = array()) {  
 if (!is\_callable($func)) {  
 throw "func is not callable";  
 }  
 $reflection = new ReflectionFunction($func);  
 $funcParams = array();

foreach ($reflection-\>getParameters() as $parameter) {  
 $name = $parameter-\>getName();

if (\_\_DEBUG\_\_) {  
 var\_dump($parameter-\>getName());  
 var\_dump($parameter-\>isOptional());  
 }

if (array\_key\_exists($name, $params)) {  
 array\_push($funcParams, $params[$name]);  
 } elseif ($parameter-\>isOptional()) {  
 array\_push($funcParams, $parameter-\>getDefaultValue());  
 } else {  
 throw new Exception("Value for parameter {$name} not found");  
 }  
 }  
 return call\_user\_func\_array($func, $funcParams);  
}

А теперь воспользуемся ей.

function foo($bar = 'bar', $baz = 'baz') {  
 echo "{$bar}, {$baz}\n";  
}

call\_user\_func\_params('foo', array('baz' =\> 'xyz'));

Выводит то, что и ожидалось.

bar, xyz

А теперь так.

call\_user\_func\_params('htmlspecialchars', array('string' =\> ""текст"", 'double\_encode' =\> false));

Облом-с.

PHP Fatal error: Uncaught exception 'ReflectionException' with message 'Cannot determine default value for internal functions' in file.php

А все потому, что пхп обрабатывает встроенные функции иначе, нежели написанные кривыми руками программиста. :)

А еще документация нас открыто уведомляет о том, что именя параметров реальные (я про встроенные функции) могут отличаться от того, что написано в спецификации.