Pergunta

Tenho certeza que a resposta a esta pergunta é não, mas caso haja algum guru de PHP

é possível escrever uma função de uma forma onde argumentos inválidos ou variáveis ​​​​inexistentes possam ser passados ​​​​e o php não erre sem o uso de '@'

Muito parecido com vazio e isset.Você pode passar uma variável que acabou de criar e não haverá erro.

ex:

empty($someBogusVar); // no error

myHappyFunction($someBogusVar); // Php warning / notice
Foi útil?

Solução

Resumindo, a resposta correta é não, você não deveria (veja advertência abaixo).

Existem soluções alternativas já mencionadas por muitas pessoas neste tópico, como usar variáveis ​​de referência ou isset() ou vazio() em condições e suprimir avisos na configuração do PHP.Isso, além da solução alternativa óbvia, usar @, que você não deseja.

Resumindo uma interessante discussão de comentários com Gerry:Passar a variável por referência é realmente válido se você verifique o valor da variável dentro da função e lidar adequadamente com casos indefinidos ou nulos.Apenas não use a passagem de referência como forma de encerrar o PHP (é para onde meu original não deveria apontar).

Outras dicas

Você não recebe nenhum erro quando a variável é passada por referência (o PHP criará uma nova variável silenciosamente):

 function myHappyFunction(&$var)
 {       
 }

Mas eu recomendo não abusar disso para ocultar erros de programação.

Você pode fazer isso usando func_get_args assim:

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";

Esta função vai um passo além e forneceria o primeiro valor não vazio de qualquer número de argumentos (você sempre pode forçá-la a receber apenas dois argumentos, mas isso me parece mais útil assim).

EDITAR:a versão original não usou compact para tentar criar um array de argumentos e AINDA deu um erro.O relatório de erros aumentou um pouco e esta nova versão com compact é um pouco menos organizada, mas ainda faz a mesma coisa e permite fornecer um valor padrão para vars inexistentes.

Existem casos válidos em que a verificação se torna complicada e desnecessária.
Portanto escrevi esta pequena função mágica:

/**
 * 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;
    }
}

Não requer nenhuma alteração em myHappyFunction().
Você terá que mudar

myHappyFunction($someBogusVar);

para

myHappyFunction(value($someBogusVar));

Declarando sua intenção explicitamente.o que faz com que boa prática no meu livro.

Não, porque isso não tem nada a ver com a função;o erro vem da tentativa de desreferenciar uma chave de matriz inexistente.Você pode alterar o nível de aviso da configuração do PHP para suprimir esses erros, mas é melhor não fazer isso.

Dito isso, você poderia faça algo como

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

  return 0;
}

E use-o no lugar da pesquisa de chave de array

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

Agora preciso tomar um banho :)

é possível escrever uma função de uma forma onde argumentos inválidos ou variáveis ​​inexistentes possam ser passados ​​e o php não irá errar sem o uso de '@'

Sim você pode!

porneL está correto [editar: não tenho pontos suficientes para vincular à resposta dele ou votar, mas está nesta página]

Ele também está correto quando adverte ", mas eu recomendo não abusar disso por ocultar erros de programação". No entanto, a supressão de erros através do operador de controle de erros (@) também deve ser evitada por esse mesmo motivo.

Sou novo no Stack Overflow, mas espero que não seja comum que uma resposta incorreta seja classificada como a mais alta em uma página enquanto a resposta correta não recebe votos.:(

@Brian:Eu uso uma operação trinária para fazer a verificação para mim:

return $value ? $value : $default;

isso retorna $value OU $default.Dependendo do valor de $value.Se for 0, falso, vazio ou algo semelhante, o valor em $default será retornado.

Estou mais propenso ao desafio de emular funções como vazia() e isset()

@Sean Isso já foi respondido por Brian

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

Sean, você poderia fazer:

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

EDITAR:

Tenho certeza de que pode haver uma ótima discussão sobre as chamadas de função dos operadores ternários.Mas o objetivo dessa questão era ver se podemos criar uma função que não lança um erro se um valor não existente for passado sem usar o '@'

E eu te disse, verifique com isset().A primeira parte de uma condicional ternária não verifica nulo ou não nulo, ela verifica true ou false.Se você tentar verificar true ou false em um valor nulo em PHP, você recebe esses avisos. isset() verifica se uma variável ou expressão retorna um valor nulo ou não, e retorna um booleano, que pode ser avaliado pela primeira parte do seu ternário sem erros.

Tenho certeza de que poderia haver uma grande discussão sobre chamadas de função de operadores ternários vrs.Mas o objetivo desta questão era ver se podemos criar uma função que não gere um erro se um valor inexistente for passado sem usar o '@'

Embora a resposta à pergunta original seja “não”, há opções que ninguém mencionou.

Quando você usa o sinal @, tudo o que o PHP faz é substituir o error_reporting nível e definindo-o temporariamente para zero.Você pode usar "ini_restore('error_reporting');" para voltar ao que era antes do @ ser usado.

Isso foi útil para mim na situação em que eu queria escrever uma função de conveniência para verificar se uma variável estava definida e também tinha outras propriedades, caso contrário, retornaria um valor padrão.Mas, enviar uma variável não definida causou um aviso do PHP, então usei o @ para suprimir isso, mas depois configurei error_reporting de volta ao valor original dentro da função.

Algo como:

$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;
     }
}

Então, no caso acima, se $bar não está definido, não receberei um erro quando ligar foo() com uma variável inexistente.No entanto, receberei um erro na função onde digitei por engano is_set em vez de isset.

Esta poderia ser uma opção útil para cobrir o que a pergunta original perguntava em espírito, se não de fato.

Se você simplesmente adicionar um valor padrão ao parâmetro, poderá ignorá-lo ao chamar a função.Por exemplo:

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

Com uma única linha você consegue: myHappyFunction($someBogusVar="");

Espero que isto seja o que procuras.Se você ler a documentação do php, em valores de argumento padrão, você pode ver que atribuir um valor padrão ao argumento de uma função ajuda a evitar uma mensagem de erro ao usar funções.

Neste exemplo você pode ver a diferença de usar um argumento padrão e suas vantagens:

Código 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);
?>

Saída para test1() linhas:

Aviso:Argumento 1 ausente para test1() .
Olá.
.
Olá Mundo.

Saída para test2() linhas:

.
Olá.

Olá Mundo.

Isto também pode ser usado em combinação para isset() e outras funções para realizar o que você deseja.

E subindo mais na árvore de abstração, para que você está usando isso?

Você pode inicializar esses valores em cada classe conforme apropriado ou criar uma classe específica contendo todos os valores e atributos padrão, como:

class Configuration {

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

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

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

}

A ideia é que, ao usar a função defaultValue em todos os lugares do seu código, ela se tornará um pesadelo de manutenção sempre que você precisar alterar um valor, procurando todos os locais onde você colocou uma chamada defaultValue.E provavelmente também levará você a se repetir, violando o DRY.

Considerando que este é um local único para armazenar todos esses valores padrão.Você pode ficar tentado a evitar a criação desses setters e getters, mas eles também ajudam na manutenção, caso seja pertinente fazer alguma modificação nas saídas ou validação de entradas.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top