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

Я почти уверен, что ответ на этот вопрос - нет, но в случае, если есть гуру PHP

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

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

ex:

empty($someBogusVar); // no error

myHappyFunction($someBogusVar); // Php warning / notice

14 ответов

Решение

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

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

Подводя итог интересному обсуждению комментария с Gerry: передача переменной по ссылке действительно допустима, если вы проверяете значение переменной внутри функции и правильно обрабатывает неопределенные или нулевые случаи. Только не используйте передачу ссылок как способ отключения 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";

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

РЕДАКТИРОВАТЬ: оригинальная версия не использовала компактный, чтобы попытаться создать массив аргументов, и STILL дал ошибку. Отчеты об ошибках поднялись на ступеньку выше, и эта новая версия с 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 не будет выдавать ошибку без использования '@'

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

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

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

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

@Sean На это уже ответил Брайан

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

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

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

РЕДАКТИРОВАТЬ:

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

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

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

return $value ? $value : $default;

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

Я больше иду на вызов для эмуляции функций, таких как empty() и isset()

Вы можете дополнить ее одной строкой: 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() и другие функции, чтобы выполнить то, что вы хотите.

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

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

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

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

Это было полезно для меня в ситуации, когда я хотел написать вспомогательную функцию для проверки и определения, установлена ​​ли переменная, а также имеет ли некоторые другие свойства, в противном случае возвращает значение по умолчанию. Но, отправка неустановленной переменной через вызвало уведомление 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,

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

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

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

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

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. И это также, вероятно, заставит вас повторить себя, нарушая СУХОЙ.

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

Другие вопросы по тегам