Pregunta

Estoy bastante seguro de que la respuesta a esta pregunta es no, pero en caso de que haya algún gurú de PHP

¿Es posible escribir una función de manera que se puedan pasar argumentos no válidos o variables inexistentes y PHP no produzca errores sin el uso de '@'

Al igual que lo hacen vacío e isset.Puede pasar una variable que acaba de crear y no generará errores.

ex:

empty($someBogusVar); // no error

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

Solución

Resumiendo, la respuesta adecuada es no, no deberías (ver advertencia a continuación).

Muchas personas en este hilo ya mencionaron soluciones alternativas, como usar variables de referencia o isset() o vacía() en condiciones y suprimir avisos en la configuración de PHP.Eso además de la solución obvia, usar @, que no deseas.

Resumiendo una interesante discusión sobre comentarios con Gerry:Pasar la variable por referencia es efectivamente válido si comprobar el valor de la variable dentro de la función y manejar casos nulos o indefinidos correctamente.Simplemente no uses el paso de referencias como una forma de cerrar PHP (aquí es donde mi original no debería señalar).

Otros consejos

No recibe ningún error cuando la variable se pasa por referencia (PHP creará una nueva variable de forma silenciosa):

 function myHappyFunction(&$var)
 {       
 }

Pero recomiendo no abusar de esto para ocultar errores de programación.

Puedes hacer esto usando func_get_args así:

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 función va un paso más allá y le daría el primer valor no vacío de cualquier número de argumentos (siempre puede forzarlo a que solo tome hasta dos argumentos, pero esto me parece más útil así).

EDITAR:La versión original no usó compact para intentar crear una serie de argumentos y TODAVÍA dio un error.El informe de errores aumentó un poco y esta nueva versión con compact es un poco menos ordenada, pero aún hace lo mismo y le permite proporcionar un valor predeterminado para vars inexistentes.

Hay casos válidos en los que la comprobación se vuelve engorrosa e innecesaria.
Por eso he escrito esta pequeña función 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;
    }
}

No requiere ningún cambio en myHappyFunction().
tendrás que cambiar

myHappyFunction($someBogusVar);

a

myHappyFunction(value($someBogusVar));

Indicando explícitamente su intención.lo que lo hace buena práctica en mi libro.

No, porque esto realmente no tiene nada que ver con la función;el error proviene de intentar eliminar la referencia a una clave de matriz inexistente.Puede cambiar el nivel de advertencia de su configuración de PHP para eliminar estos errores, pero es mejor que no lo haga.

Dicho esto, usted podría hacer algo como

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

  return 0;
}

Y úselo en lugar de la búsqueda de claves de matriz

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

Ahora necesito darme una ducha :)

¿Es posible escribir una función de manera que se puedan pasar argumentos no válidos o variables inexistentes y PHP no genere errores sin el uso de '@'?

¡Sí tu puedes!

porneL es correcto [editar: no tengo suficientes puntos para vincular su respuesta o votarla, pero está en esta página]

También tiene razón cuando advierte "pero recomiendo no abusar de esto para ocultar los errores de programación". Sin embargo, la supresión de errores a través del operador de control de errores (@) también debe evitarse por esta misma razón.

Soy nuevo en Stack Overflow, pero espero que no sea común que una respuesta incorrecta ocupe el puesto más alto en una página mientras que la respuesta correcta no recibe votos.:(

@Brian:Utilizo una operación trinaria para hacer la verificación por mí:

return $value ? $value : $default;

esto devuelve $valor O $predeterminado.Dependiendo del valor de $value.Si es 0, falso, vacío o algo similar, se devolverá el valor en $default.

Prefiero el desafío de emular funciones como vacía() e isset()

@Sean Eso ya fue respondido por Brian

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

Sean, podrías hacer:

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

EDITAR:

Estoy seguro de que podría haber una gran discusión sobre las llamadas de la función VRS de los operadores ternarios.Pero el punto de esta pregunta era ver si podemos crear una función que no arroje un error si se pasa un valor no existente sin usar el '@'

Y te dije, compruébalo con isset().La primera parte de un condicional ternario no verifica que sea nulo o no nulo, verifica true o false.Si intentas comprobar true o false en un valor nulo en PHP, obtienes estas advertencias. isset() comprueba si una variable o expresión devuelve un valor nulo o no, y devuelve un booleano, que puede ser evaluado por la primera parte de su ternario sin ningún error.

Estoy seguro de que podría haber una gran discusión sobre las llamadas a funciones de operadores ternarios vrs.Pero el objetivo de esta pregunta era ver si podemos crear una función que no arroje un error si se pasa un valor inexistente sin usar '@'.

Si bien la respuesta a la pregunta original es "no", hay opciones que nadie ha mencionado.

Cuando usas el signo @, todo lo que PHP hace es anular el error_reporting nivel y ponerlo temporalmente a cero.Puedes usar "ini_restore('error_reporting');" para restablecerlo a lo que era antes de que se usara @.

Esto fue útil para mí en la situación en la que quería escribir una función de conveniencia para verificar y ver si una variable estaba configurada y si también tenía otras propiedades; de lo contrario, devolver un valor predeterminado.Pero, enviar una variable no configurada provocó un aviso de PHP, así que usé @ para suprimir eso, pero luego configuré error_reporting volver al valor original dentro de la función.

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

Entonces, en el caso anterior, si $bar no está configurado, no recibiré un error cuando llame foo() con una variable inexistente.Sin embargo, recibiré un error dentro de la función donde escribí por error is_set en lugar de isset.

Esta podría ser una opción útil que cubra lo que la pregunta original planteaba en espíritu, si no en los hechos.

Si simplemente agrega un valor predeterminado al parámetro, puede omitirlo al llamar a la función.Por ejemplo:

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

Con una sola línea podrás lograrlo: myHappyFunction($someBogusVar="");

Espero que esto sea lo que estás buscando.Si lees la documentación de php, en valores de argumento predeterminados, puede ver que asignar un valor predeterminado al argumento de una función le ayuda a evitar un mensaje de error al utilizar funciones.

En este ejemplo puedes ver la diferencia de usar un argumento predeterminado y sus ventajas:

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);
?>

Salida para test1() líneas:

Advertencia:Falta el argumento 1 para test1() .
Hola.
.
Hola Mundo.

Salida para test2() líneas:

.
Hola.

Hola Mundo.

Esto también se puede utilizar en combinación para isset() y otras funciones para lograr lo que deseas.

Y yendo más arriba en el árbol de abstracción, ¿para qué estás usando esto?

Puede inicializar esos valores en cada clase según corresponda o crear una clase específica que contenga todos los valores y atributos predeterminados, como:

class Configuration {

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

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

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

}

La idea es que, cuando utilices la función defaultValue en todas partes de tu código, se convertirá en una pesadilla de mantenimiento cada vez que tengas que cambiar un valor, buscando todos los lugares donde has puesto una llamada defaultValue.Y probablemente también te llevará a repetirte, violando DRY.

Mientras que este es un lugar único para almacenar todos esos valores predeterminados.Podría verse tentado a evitar crear esos definidores y captadores, pero también ayudan en el mantenimiento, en caso de que sea pertinente realizar alguna modificación de las salidas o validación de las entradas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top