PHP quirks и ловушки
Я понял, что, хотя большая часть моего опыта заключается в написании приложений PHP, я время от времени нахожу себя "начинающими ошибками". Это потому, что PHP - это язык, который вырос очень органично и, как таковой, имеет некоторые особенности, причуды и ловушки, о которых я не знаю.
Я бы хотел, чтобы этот вопрос был вики для всех тех, кто хочет знать ошибки PHP и исключения из того, что мы можем считать правилами. Но, пожалуйста, не пишите общие ответы вроде:
Некоторые функции принимают аргументы как $needle
, $haystack
, а некоторые как $haystack
, $needle
.
Сообщите именам функций. У вас есть несколько ответов от меня в качестве примеров. О, и добавьте одну ошибку за каждый ответ. Таким образом, мы увидим, что наиболее презирает их всех (путем голосования).
Я не хочу начинать пламенную войну, держать ее в теме. Если вы хотите написать некоторые плохие вещи о PHP, сделайте это как комментарий к соответствующему ответу.
Надеюсь, эта вики поможет всем нам, новичкам и экспертам.
Update:
После комментария Андрея Мора я думаю, что ответ должен также содержать решение или обходной путь для ловушки.
Ответы
Ответ 1
Сериализация объектов, которые обрабатывают структуры 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.
Ответ 2
Нестандартный приоритет оператора.
$x = 1;
echo 'foo: ' . $x+1 . ' bar';
Выведет: "1 bar
" вместо ожидаемого "foo: 2 bar
". Решение. Используйте скобки.
Ответ 3
Я ненавижу, как вы можете получить проблемы, если вы закрываете php файлы с закрывающим тегом ?>
(похоже, что это должно быть наоборот). Например, добавьте файл с некоторым пробелом после? > , А затем попробуйте изменить заголовки (при отсутствии буферизации вывода). UGH. Я долго хотел научиться никогда не закрывать php файлы с помощью ?>
Ответ 4
Integer размер зависит от платформы. Обычно вы не можете использовать 64-битные целые числа на 32-битной машине без внешнего модуля. Кроме того, вы не можете объявить целые числа без знака.
Ответ 5
Несколько способов выполнения тестов на истинность (не оператор, empty(), is_null(), isset()) + слабое типирование = this
С некоторой дисциплиной вы можете избежать необходимости обращаться к этой таблице:
-
Для общих тестов истинности вы можете использовать логическое сравнение if ($)
{...} if (!$x) { ... }
. Он ведет себя так, как делают логические операторы на большинстве языков.
-
Всегда используйте empty()
, если вы хотите протестировать ввод формы для значений ложности (это относится к "0" как false).
-
Всегда используйте isset()
, если вы хотите определить, где установлена переменная или нет.
-
Используйте is_null()
или $x === NULL
, если вам нужно только проверить NULL
Ответ 6
У меня было всевозможное беспокойство, объединяющее 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 стало лучше, если вы не используете явные ссылки, я все равно получаю от этого время.
Ответ 7
Несогласованные соглашения об именах встроенных функций. Например, этот набор функций обработки строк:
str_shuffle()
str_split()
str_word_count()
strcasecmp()
strchr()
strcmp()
Решение. Всегда оставляйте ручное открывание.
Ответ 8
Некоторые недавно появившиеся функции PHP падают, потому что нет гарантии, что они будут поддерживаться по умолчанию в средах размещения.
Самая большая моя проблема - это параметр short_tags
, который позволяет использовать синтаксис тегов <? foobar(); ?>
и <?=$var ?>
. Я утверждаю, что PHP должен был включить эту функцию по умолчанию, а не отказаться.
== EDIT ==
В PHP >= 5.4 параметр short_tags
больше не учитывается в сокращенном выражении echo, поэтому он будет доступен в каждой среде хостинга, которая поддерживает PHP 5.4 и выше.
Ответ 9
Наличие функций по-разному работает на разных ОС, а некоторые функции доступны только для определенных ОС.
Например, функция mail()
в Windows не может принимать имя отправителя в параметре $to
. Он может содержать только адрес электронной почты. В Linux все работает нормально.
Другой пример: функция strptime()
доступна только в Linux, а не в Windows (это привело меня к существующему проекту, который я хотел запустить в своем окне Windows).
Конечно, есть некоторые функции, которые имеют смысл только на некоторых ОС (например, на функциях Win32API), но многим кажется, что они должны вести себя одинаково на всех ОС, когда на самом деле они этого не делают.
Ответ 10
Иногда вам нравится передавать функцию-результат в другую функцию напрямую, которая принимает только переменные в качестве входных данных.
Например:
array_pop( explode('\\', get_class($this)) )
... приведет к ошибке E_STRICT " Только переменные должны передаваться по ссылке". Чтобы заставить его работать, просто добавьте еще одну пару скобок вокруг внутреннего (возвращенного) оператора:
array_pop( (explode('\\', get_class($this))) )
(Если вы используете пространства имен и расширенные классы, эта строка возвращает только имя класса (без пространства имен) из вызывающего объекта, а не родительский класс, который был расширен и может содержать эту функцию.)
Ответ 11
Хотя строки могут быть итерированы с использованием циклов for
и индексов, они не могут быть повторены с использованием циклов 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() ...
Ответ 12
мой любимый:
<?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)';
Ответ 13
== EDIT ==
Это больше не относится к PHP >= 5.5!
Я иногда сталкиваюсь с ошибкой 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)) {
// ...
}
Ответ 14
$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