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. Я все еще выясняю.