Стратегия PHP и неопределенных переменных - PullRequest
14 голосов
/ 25 августа 2010

Я программист на C ++, начинающий с PHP.Я обнаружил, что теряю большую часть времени отладки (и мою самооценку!) Из-за неопределенных переменных.Из того, что я знаю, единственный способ справиться с ними - это посмотреть результат во время выполнения.

Есть ли другие стратегии, чтобы заметить раньше эти недостатки?(что-то вроде C ++, когда одна компиляция дает вам все необходимые подсказки)

Спасибо за любые идеи

Ответы [ 12 ]

10 голосов
/ 25 августа 2010

Это распространенная жалоба на PHP.Вот несколько идей:

  1. Используйте инструмент анализа кода .Также помогут многие IDE, такие как Netbeans .

  2. Просто запустите код. В PHP нет дорогостоящего этапа компиляции, как в C ++.

  3. Использовать модульное тестирование.Общие побочные эффекты включают в себя: лучший код.

  4. Set error_reporting(-1) или эквивалент в вашем INI-файле .

  5. Получить xdebug .Это не является предупреждением, но трассировка стека помогает при обнаружении ошибок.

  6. isset(), === null (идентификационный оператор) и охранникпункты - ваши друзья.

Свободная и динамическая типизация является особенностью языка.Тот факт, что PHP не является строгим при наборе , не означает, что вы не можете.Если вас это действительно беспокоит, и у вас есть выбор, вы можете вместо этого попробовать Python - это немного сложнее при наборе текста.

6 голосов
/ 25 августа 2010

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

5 голосов
/ 25 августа 2010

Нет.В 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.

2 голосов
/ 25 августа 2010

Если я что-то упустил, то почему никто не предлагает правильно структурировать вашу страницу?У меня никогда не было постоянной проблемы с неопределенными ошибками переменных.

Идея структурирования вашей страницы

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

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

alt text

Никому не нравится код spagehtti

Если вы покажете нам часть своего кода, мы сможем предложить предложения о том, как выможет лучше структурировать это, чтобы разрешить подобные ошибки.Вы можете запутаться из-за фона C, поток может работать иначе, чем веб-страницы.

2 голосов
/ 25 августа 2010

На этапах разработки используйте

error_reporting(E_ALL);

. Ведьма покажет каждую вызванную ошибку, все ошибки УВЕДОМЛЕНИЯ и т. Д.

Также обратите внимание на 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 для переменных, которые вы можете / можетеnot set из-за оператора if, скажем.

всегда используйте if(isset($_POST['key'])) или, что еще лучше, просто используйте if(!empty($_POST['key'])), так как это проверяет, существует ли ключ и не пусто ли значение.

убедитесь, что вы также хорошо знаете свои операторы сравнения, языки вроде C # используют == для проверки состояния bool, где как в php для проверки типов данных вы должны использовать === и использовать == для проверки состояний значений, а также одиночный = чтобы присвоить значение!

2 голосов
/ 25 августа 2010

Просто следите за тем, чтобы не выполнять операции, требующие значения переменной при первом использовании, например, оператор concat. =

Если вы программист на C ++, вы должны быть использованы для объявления всех переменных, выполните аналогичные действия вPHP путем обнуления переменных или создания пустого массива, если вы хотите их использовать.

Обратите внимание на пользовательский ввод, убедитесь, что вы отключили регистры глобальных переменных и проверьте входные данные из $ _GET и $ _POST с помощью isset ().

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

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

2 голосов
/ 25 августа 2010

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

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

$my_var = value;

Используя синтаксис phpDocumentor, вы также можете объявить, что они имеют определенный тип, по крайней мере таким образом, что многие IDE могут выполнять поиск кода с помощью:

/** @desc optional description of what the variable does
    @var int */
$my_var = 0;

Кроме того, вы можете (и иногда нужно) использовать условия isset() / empty() / array_key_exists() перед попыткой доступа к переменной.

Я согласен, иногда это отстой , но это необходимо. В готовом производственном коде не должно быть уведомлений - они снижают производительность, даже если их отображение отключено, плюс они очень полезны для обнаружения опечаток, которые можно было сделать при использовании переменной. (Но вы уже это знаете.)

1 голос
/ 25 августа 2010

если вы хотите скрыть ошибку неопределенной переменной, используйте @. пример: @$var

1 голос
/ 25 августа 2010

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

$ variable = default_value;

Это решит большинство проблем. Как предлагалось ранее, используйте xdebug или встроенные средства отладки в редакторах, таких как Netbeans

0 голосов
/ 10 января 2019

Это старый вопрос, но я действительно не нашел прямого ответа уже здесь.Фактическое решение, которое я нашел для этой проблемы, состоит в том, чтобы использовать PHP Code Sniffer вместе с этим удивительным расширением под названием PHP Code Sniffer Variable Analysis .

Также обычный PHP-линтер (php -l) доступен внутри PHP Code Sniffer, так что я подумываю настроить свою конфигурацию для регулярного линтинга PHP, обнаружить неиспользуемые / неинициализированные переменные и проверить собственный стиль кода, и все это за один шаг.

Редактировать: Мойочень минимальная конфигурация PHPCS:

<?xml version="1.0"?>
<ruleset name="MyConfig">
    <description>Minimal PHP Syntax check</description>
    <rule ref="Generic.PHP.Syntax" />
    <rule ref="VariableAnalysis" />
</ruleset>
...