PHP и стратегия undefined
Я программист на С++, начиная с PHP. Я обнаружил, что теряю большую часть времени отладки (и мою самооценку!) Из-за переменных undefined. Из того, что я знаю, единственный способ справиться с ними - следить за выходом во время выполнения.
Существуют ли другие стратегии для выявления раненых этих недостатков? (что-то вроде с С++, что один компилятор дает вам все необходимые подсказки)
Спасибо за любые идеи
Ответы
Ответ 1
Это распространенная жалоба на PHP. Вот несколько идей:
-
Используйте инструмент анализа кода. Многие IDE, такие как Netbeans, также помогут.
-
Просто запустите код. PHP не имеет дорогостоящего этапа компиляции, например, С++.
-
Используйте модульное тестирование. Общие побочные эффекты включают: лучший код.
-
Установите error_reporting(-1)
или эквивалент в ini.
-
Получить xdebug. Это не превентивный, но трассировки стека помогают с хрустящими ошибками.
-
isset()
, === null
(оператор идентичности), а также предложения охраны - ваши друзья.
Свободная и динамическая типизация - это особенность языка. Просто потому, что PHP не является строгим в отношении ввода, не означает, что вы не можете быть. Если это действительно вас задевает, и у вас есть выбор, вы можете попробовать Python вместо этого, он немного строже с типом.
Ответ 2
Зарегистрируйте свои сообщения E_NOTICE в текстовом файле. Затем вы можете обрабатывать журналы с автоматическими сценариями, чтобы указать файлы и строки, в которых они были подняты.
Ответ 3
Нет. В PHP вы можете знать только, что переменная не существует при попытке получить к ней доступ.
Рассмотрим:
if ($data = file('my_file.txt')) {
if (count($data) >= 0)
$line = reset($data);
}
var_dump($line);
Вы должны перестроить свой код, чтобы все пути кода приводили к определенной переменной, например:
$line = "default value";
if ($data = file('my_file.txt')) {
if (count($data) >= 0)
$line = reset($data);
}
var_dump($line);
Если значения по умолчанию не установлены, это все равно лучше, чем isset
, потому что вы будете предупреждены, если у вас есть опечатка в имени переменной в окончательном if
:
$line = null;
if ($data = file('my_file.txt')) {
if (count($data) >= 0)
$line = reset($data);
}
if ($line !== null) { /* ... */ }
Конечно, вы можете использовать isset
1 для проверки в данной точке, если существует переменная. Однако, если ваш код полагается на это, он, вероятно, плохо структурирован. Я хочу сказать, что, вопреки, например, C/Java, во время компиляции вы не можете определить, действителен ли доступ к переменной. Это усугубляется отсутствием области блока в PHP.
1 Строго говоря, isset
не скажет вам, установлена ли переменная, она указывает, установлена ли она и не равна нулю. В противном случае вам понадобится get_defined_vars
.
Ответ 4
Из того, что я знаю, единственный способ справиться с ними - следить за выходом во время выполнения.
Не совсем: Чтобы предотвратить появление этих уведомлений, вам просто нужно убедиться, что вы инициализируете переменные перед их первым входом. Мы (к сожалению, ИМО) не имеем объявления переменных в PHP, но инициализация их в начале вашего кода также справедлива:
$my_var = value;
Используя синтаксис phpDocumentor, вы также можете объявить их определенным типом, по крайней мере таким образом, чтобы многие IDE могли выполнять поиск кода с помощью:
/** @desc optional description of what the variable does
@var int */
$my_var = 0;
Кроме того, вы можете (и иногда необходимо) использовать условия isset()
/empty()
/array_key_exists()
, прежде чем пытаться получить доступ к переменной.
Я согласен, что это отстойное время, но это необходимо. В готовом коде не должно быть никаких уведомлений - они потребляют производительность, даже если отображение их выключено, а также очень полезно узнать опечатки, которые можно было бы сделать при использовании переменной. (Но вы уже это знаете.)
Ответ 5
Просто наблюдайте за тем, чтобы не выполнять операции, требующие значения переменной при первом использовании, например, оператор concat. =
Если вы программист на С++, вы должны использовать для объявления всех переменных. Сделайте что-нибудь подобное в PHP с помощью нулевых переменных или создайте пустой массив, если вы хотите их использовать.
Обратите внимание на ввод пользователя, убедитесь, что вы заблокировали глобальные регистры и проверьте входы от $_GET и $_POST на isset().
Вы также можете попробовать кодировать классы против структурного кода и иметь каждую переменную, созданную при начале объявления класса, с правильной политикой конфиденциальности.
Вы также можете отделить логику приложения от представления, подготовив все переменные, которые должны быть выведены в первую очередь, и когда он появится, чтобы отобразить его, вы будете знать, какие переменные вы подготовили.
Ответ 6
На этапах разработки используйте
error_reporting(E_ALL);
witch будет показывать каждую вызванную ошибку, все ошибки УВЕДОМЛЕНИЯ и т.д.
Следите за своим error_log
и покажите свои ошибки
используйте систему отчетов об ошибках, например:
http://php.net/manual/en/function.set-error-handler.php
class ErrorReporter
{
public function catch($errno, $errstr, $errfile, $errline)
{
if($errno == E_USER_NOTICE && !defined('DEBUG'))
{
//Catch all output buffer and clear states, redirect or include error page.
}
}
}
set_error_handler(array(new ErrorReporter,'catch'));
несколько других советов всегда используют isset
для переменных, которые вы можете/не могли установить из-за утверждения if. Скажем,
всегда используйте if(isset($_POST['key']))
или даже лучше просто используйте if(!empty($_POST['key']))
, поскольку это проверяет, существует ли ключ, и если значение НЕ пусто.
убедитесь, что вы знаете своих операторов сравнения, а также языки, такие как С# use ==, чтобы проверить состояние bool, где, как и в php, для проверки типов данных, которые вы должны использовать ===
, и использовать ==
для проверки состояний значений и одиночных =
, чтобы присвоить значение!
Ответ 7
Если мне что-то не хватает, почему никто не предлагает правильно структурировать вашу страницу? У меня никогда не возникало проблемы с ошибками переменной undefined.
Идея структурирования вашей страницы
Определите все ваши переменные вверху, присвойте значения по умолчанию, если необходимо, а затем используйте эти переменные. Это то, как я пишу веб-страницы, и я никогда не сталкиваюсь с проблемами undefined.
Не входите в привычку определять переменные только тогда, когда они вам нужны, это быстро создает код спагетти и может быть очень трудным для управления.
![alt text]()
Никто не любит код spagehtti
Если вы покажете нам часть своего кода, мы можем предложить предложения о том, как вы можете лучше структурировать его для устранения таких ошибок. Возможно, вы сбились с толку на фоне C, поток может работать по-разному с веб-страницами.
Ответ 8
Хорошая практика состоит в том, чтобы определить всю переменную перед использованием. i. установить значение по умолчанию
$variable = default_value;
Это решит большинство проблем. Как было предложено перед использованием xdebug или встроенными средствами отладки в редакторах, таких как Netbeans
Ответ 9
если вы хотите скрыть ошибку переменной undefined, а затем используйте @.
Пример: @$var
Ответ 10
Спасибо всем за ваши ответы. Я был довольно обеспокоен поиском опечаток, но, поскольку я врывался в PHP и ваши ответы, я вижу, что язык в значительной степени отличается от С++. Возможность создания динамических переменных присуща языку. Возможно, в будущей версии некоторые опции принудительного объявления переменных для каждого модуля за счет этого динамизма были бы полезны для некоторых проектов.
Ответ 11
Я считаю, что различные инструменты Code Coverage, доступные для PHP, подчеркнут это.
Ответ 12
Лично я пытаюсь установить переменные, даже если это с пустой строкой, массивом, Boolean и т.д. Затем используйте функцию, например isset()
, прежде чем использовать их. Например:
$page_found = false;
if ($page_found==false) {
// do page not found stuff here
}
if (isset($_POST['field'])) {
$value = $_POST['field'];
$sql = "UPDATE table SET field = '$value'";
}
И так далее. И прежде чем какая-то умная задница скажет это: я знаю, что запрос небезопасен. Это был всего лишь пример использования isset()
.
Ответ 13
Это старый вопрос, но я действительно не нашел прямого ответа уже здесь. Фактическое решение, которое я нашел для этой проблемы, состоит в том, чтобы использовать PHP Code Sniffer вместе с этим удивительным расширением, называемым PHP Code Sniffer Variable Analysis.
Также в PHP Code Sniffer доступен обычный PHP-линтер (php -l), поэтому я подумываю настроить свою конфигурацию для обычного PHP-линтинга, обнаружить неиспользуемые/неинициализированные переменные и проверить мой собственный стиль кода, и все это за один шаг.
Настроить конфигурацию немного сложно, даже это предположительно задокументировано в их репозиториях Github. Я все еще выясняю.