PHP quirks и ловушки

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

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

Некоторые функции получают аргументы в виде $needle , $haystack , а некоторые – $haystack , $needle .

Скажите имена функций. У вас есть несколько ответов от меня в качестве примеров. О, и добавьте одну ошибку за каждый ответ. Таким образом, мы увидим, что наиболее презирает их всех (путем голосования).

Я не хочу начинать пламенную войну, держать ее в курсе. Если вы хотите написать некоторые плохие вещи о PHP, сделайте это как комментарий к соответствующему ответу.

Надеюсь, эта вики поможет всем нам, новичкам и экспертам.

Обновить:

После комментария Эндрю Мура я думаю, что ответ должен также содержать решение или обходной путь для ловушки.

Solutions Collecting From Web of "PHP quirks и ловушки"

Сериализация объектов, которые обрабатывают структуры XML, а затем их неэтериализацию не восстанавливает исходную структуру XML:

 $dom = new DOMDocument; $dom->loadXML('<test/>'); $dom = serialize($dom); $dom = unserialize($dom); var_dump($dom->saveXML()); // $ Warning: DOMDocument::saveXML(): Couldn't fetch DOMDocument in ... // $ NULL 

Аналогично для объектов SimpleXML.

Нестандартный приоритет оператора.

 $x = 1; echo 'foo: ' . $x+1 . ' bar'; 

Будет выводиться: « 1 bar », вместо ожидаемого « foo: 2 bar ». Решение. Используйте скобки.

Я ненавижу, как вы можете получить проблемы, если вы закрываете php-файлы с закрывающим тегом ?> (Похоже, это должно быть наоборот). Например, добавьте файл с некоторым пробелом после?>, А затем попробуйте изменить заголовки (при отсутствии буферизации вывода). UGH. Взял ли я путь, чтобы научиться никогда не закрывать php-файлы ?>

Целочисленный размер зависит от платформы. Обычно вы не можете использовать 64-битные целые числа на 32-битной машине без внешнего модуля. Кроме того, вы не можете объявлять целые числа без знака.

Несколько способов выполнения тестов на истинность ( не оператор , empty () , is_null () , isset () ) + слабый ввод = this

С некоторой дисциплиной вы можете в основном избежать необходимости ссылаться на эту таблицу:

  • Для общих тестов истинности вы можете использовать логическое сравнение if ($) {…} if (!$x) { ... } . Он ведет себя так, как это делают логические операторы на большинстве языков.

  • Всегда используйте empty() если вы хотите проверить ввод формы для значений ложных значений (это относится к «0» как false).

  • Всегда используйте isset() если вы хотите определить, где установлена ​​переменная или нет

  • Используйте is_null() или $x === NULL если вам нужно только проверить NULL

У меня было всевозможное беспокойство, объединяющее foreach со ссылками

 $testarray = array(1 => "one", 2 => "two"); $item = "three"; $testarray[3] =& $item; foreach ($testarray as $key => $item) { // do nothing } echo $testarray[3]; // outputs "two" 

Это действительно отбросило меня в эпоху PHP4, и, хотя в PHP5 стало лучше в PHP5, если вы не используете явные ссылки, мне все равно удается зацепиться за это время от времени.

Несогласованные соглашения об именах встроенных функций. Например, этот набор функций обработки строк:

  str_shuffle() str_split() str_word_count() strcasecmp() strchr() strcmp() 

Решение. Оставьте ручку открытой в любое время.

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

Например, функция mail() в Windows не может принимать имя отправителя в параметре $to . Он может содержать только адрес электронной почты. В Linux все работает нормально.

Другой пример: функция strptime() доступна только в Linux, а не в Windows (это strptime() меня к существующему проекту, который я хотел запустить в своем окне Windows).

Конечно, есть некоторые функции, которые имеют смысл только на некоторых ОС (например, на функциях Win32API), но многим кажется, что они должны вести себя одинаково на всех ОС, когда на самом деле они этого не делают.

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

Например:

 array_pop( explode('\\', get_class($this)) ) 

… приведет к ошибке E_STRICT « Только переменные должны передаваться по ссылке ». Чтобы заставить его работать, просто добавьте еще одну пару скобок вокруг внутреннего (возвращенного) оператора:

 array_pop( (explode('\\', get_class($this))) ) 

(Если вы используете пространства имен и расширенные классы, эта строка возвращает только имя класса (без пространства имен) из вызывающего объекта, а не родительский класс, который был расширен и может содержать эту функцию.)

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

Самая большая моя ручка – это параметр short_tags который позволяет <? foobar(); ?> <? foobar(); ?> <? foobar(); ?> и <?=$var ?> . Я утверждаю, что PHP должен был включить эту функцию по умолчанию, а не входить.

== EDIT ==

В PHP> = 5.4 параметр short_tags больше не учитывается в сокращенном выражении echo, поэтому он будет доступен в каждой среде хостинга, которая поддерживает PHP 5.4 и выше.

Хотя строки можно повторить с использованием циклов и индексов, они не могут быть повторены с использованием петель foreach . Пример:

 $str = 'foo'; $max = strlen($str); for ($i=0; $i<$max; $i++) { echo $str[$i]; } // outputs: foo foreach ($str as $char) { echo $char; } // Warning: Invalid argument supplied for foreach() ... 

мой любимый:

 <?php $a = 0; $b = 'x'; var_dump(FALSE == $a); var_dump($a == $b); var_dump($b == TRUE); echo' <br />Conclusion: TRUE equals FALSE (at least in PHP)'; 

== EDIT == Это больше не верно для PHP> = 5.5!

То, что я иногда запускаю, – это Fatal error: Can't use function return value in write context ошибке Fatal error: Can't use function return value in write context при использовании empty() конструкции. Например:

 if (!empty(trim($_GET['s']))) { // ... } 

empty() требует переменную, все остальное приведет к ошибке.

Решение:

 $s = trim($_GET['s']); if (!empty($s)) { // ... } 
 $x = "a string"; if ($x == 142) { echo "lol, of course $x is a number"; } else { echo "$x is clearly not equal to 142"; } 

При запуске:

 lol, of course a string is a number 

Вы должны использовать ===

 $x = "a string"; if ($x === 142) { echo "lol, of course $x is a number"; } else { echo "$x is clearly not equal to 142"; } 

При запуске:

 a string is clearly not equal to 142