Подавление ошибок аргумента функции Php, эмуляция empty() isset()

StackOverflow https://stackoverflow.com/questions/55060

Вопрос

Я почти уверен, что ответ на этот вопрос отрицательный, но на случай, если есть какой-нибудь PHP-гуру

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

Очень похоже на то, что делают empty и isset.Вы можете передать переменную, которую вы только что создали, и это не приведет к ошибке.

ex:

empty($someBogusVar); // no error

myHappyFunction($someBogusVar); // Php warning / notice
Это было полезно?

Решение

Подводя итог, правильный ответ таков нет, тебе не следует (смотрите предостережение ниже).

Существуют обходные пути, уже упомянутые многими людьми в этой теме, такие как использование ссылочных переменных или isset() или empty() в conditions и подавление уведомлений в конфигурации PHP.Это в дополнение к очевидному обходному пути, использующему @, который вам не нужен.

Подводя итог интересному обсуждению комментариев с Джерри:Передача переменной по ссылке действительно допустима, если вы проверьте значение переменной внутри функции и правильно обрабатывать неопределенные или нулевые случаи.Только не используйте передачу ссылок как способ отключить PHP (на это не должен указывать мой оригинал).

Другие советы

Вы не получаете никакой ошибки, когда переменная передается по ссылке (PHP создаст новую переменную автоматически).:

 function myHappyFunction(&$var)
 {       
 }

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

Вы можете сделать это с помощью func_get_args следующим образом:

error_reporting(E_ALL);
ini_set('display_errors', 1);

function defaultValue() {
    $args = func_get_args();

    foreach($args as $arg) {
        if (!is_array($arg)) {
            $arg = array($arg);
        }
        foreach($arg as $a) {
            if(!empty($a)) {
                return $a;
            }
        }
    }

    return false;
}

$var = 'bob';

echo defaultValue(compact('var'), 'alpha') . "\n"; //returns 'bob'
echo defaultValue(compact('var2'), 'alpha') . "\n"; //returns 'alpha'
echo defaultValue('alpha') . "\n"; //return
echo defaultValue() . "\n";

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

Редактировать:оригинальная версия не использовала compact для создания массива аргументов и ВСЕ равно выдавала ошибку.Отчеты об ошибках выросли на ступеньку выше, и эта новая версия с compact немного менее аккуратна, но по-прежнему выполняет то же самое и позволяет вам указывать значение по умолчанию для несуществующих переменных.

Существуют допустимые случаи, когда проверка становится громоздкой и ненужной.
Поэтому я написал эту маленькую волшебную функцию:

/**
 * Shortcut for getting a value from a possibly unset variable.
 * Normal:
 *   if (isset($_GET['foo']) && $_GET['foo'] == 'bar') {
 * Short:
 *   if (value($_GET['foo']) == 'bar') {
 *
 * @param mixed  $variable 
 * @return mixed  Returns null if not set
 */
function value(&$variable) {
    if (isset($variable)) {
        return $variable;
    }
}

Это не требует каких-либо изменений в myHappyFunction().
Тебе придется измениться

myHappyFunction($someBogusVar);

Для

myHappyFunction(value($someBogusVar));

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

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

Сказав это, вы мог бы сделайте что-то вроде

function safeLookup($array, $key)
{
  if (isset($array, $key))
    return $array[$key];

  return 0;
}

И используйте его вместо поиска по ключу массива

defaultValue(safeLookup($foo, "bar"), "baz);

А теперь мне нужно принять душ :)

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

Да, ты можешь!

порнеЛ прав [правка: у меня недостаточно баллов, чтобы сослаться на его ответ или проголосовать за него, но он есть на этой странице]

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

Я новичок в Stack Overflow, но я надеюсь, что это не редкость, когда неправильный ответ получает наивысший рейтинг на странице, в то время как правильный ответ не получает голосов.:(

@Брайан:Я использую тройную операцию, чтобы выполнить проверку за меня:

return $value ? $value : $default;

это возвращает либо $value, ЛИБО $default.В зависимости от значения $value.Если оно равно 0, false, пустое или что-то подобное, будет возвращено значение в $default.

Я больше склоняюсь к задаче эмулировать такие функции, как empty() и isset()

@Шон, Брайан уже ответил на этот вопрос

return isset($input) ? $input : $default;

Шон, ты мог бы сделать:

$result = ($func_result = doLargeIntenseFunction()) ? $func_result : 'no result';

Редактировать:

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

И я сказал тебе, проверь это с помощью isset().Первая часть троичного условия не проверяет null или не null, она проверяет true или false.Если вы попытаетесь проверить true или false при нулевом значении в PHP вы получаете эти предупреждения. isset() проверяет, возвращает ли переменная или выражение нулевое значение или нет, и возвращает логическое значение, которое может быть вычислено первой частью вашего тернарного кода без каких-либо ошибок.

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

Хотя ответ на первоначальный вопрос - "нет", есть варианты, о которых никто не упоминал.

Когда вы используете знак @, все, что делает PHP, - это переопределяет error_reporting уровень и временно устанавливаем его на ноль.Вы можете использовать "ini_restore('error_reporting');" чтобы вернуть ему значение, каким оно было до использования @.

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

Что -то вроде:

$var = @foo($bar);

function foo($test_var)
{
     ini_restore('error_reporting');

     if(is_set($test_var) && strlen($test_var))
     {
          return $test_var;
     }
     else
     {
          return -1;
     }
}

Итак, в приведенном выше случае, если $bar не установлен, я не получу сообщение об ошибке при вызове foo() с несуществующей переменной.Однако я получу сообщение об ошибке из функции, в которой я ошибочно ввел is_set вместо того, чтобы isset.

Это могло бы быть полезным вариантом, охватывающим то, что задавалось в первоначальном вопросе по духу, если не на самом деле.

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

function empty($paramName = ""){
    if(isset($paramName){
        //Code here
    }
    else if(empty($paramName)){
        //Code here
    }
}

С помощью одной строки вы можете завершить его: myHappyFunction($someBogusVar="");

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

В этом примере вы можете увидеть разницу в использовании аргумента по умолчанию и его преимущества:

PHP - код:

<?php
function test1($argument)
{
    echo $argument;
    echo "\n";
}

function test2($argument="")
{
    echo $argument;
    echo "\n";
}

test1();
test1("Hello");
test1($argument);
$argument = "Hello world";
test1($argument);

test2();
test2("Hello");
test2($argument);
$argument = "Hello world";
test2($argument);
?>

Вывод для test1() линии:

Предупреждение:Отсутствует аргумент 1 для test1() .
Здравствуйте.
.
Привет, мир.

Вывод для test2() линии:

.
Здравствуйте.

Привет, мир.

Это также может быть использовано в сочетании с isset() и другие функции для достижения того, чего вы хотите.

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

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

class Configuration {

    private var $configValues = array( 'cool' => 'Defaultcoolval' ,
                                       'uncool' => 'Defuncoolval'  );

    public setCool($val) {
        $this->configValues['cool'] = $val;
    }

    public getCool() {
        return $this->configValues['cool'];
    }

}

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top