La mejor manera de dar a una variable un valor predeterminado (simular Perl ||, ||= )

6 minutos de lectura

avatar de usuario
barrena tom

Me encanta hacer este tipo de cosas en Perl: $foo = $bar || $baz asignar $baz a $foo si $bar está vacío o indefinido. Tu también tienes $foo ||= $bletch que sólo asignará $bletch a $foo si $foo no está definido o vacío.

El operador ternario en esta situación es tedioso y fastidioso. ¿Seguramente hay un método simple y elegante disponible en PHP?

¿O es la única respuesta una función personalizada que usa isset ()?

  • Relacionado en Revisión de código: codereview.stackexchange.com/q/12722/31433

    – Palec

    8 de agosto de 2015 a las 1:28

  • Por cierto, los operadores de Perl con la funcionalidad deseada son // y //= y existen a partir de Perl v5.10.0. El original || y ||= prueba el valor lógico, no la definición.

    – Palec

    8 de agosto de 2015 a las 1:33


  • @Palec, ¿por qué se identificaría una pregunta de hace 4 años con 29 votos a favor como un duplicado de una pregunta de hace 1 año con 6 votos a favor (que a su vez se marcó como un duplicado de otra pregunta?) Creo que es de gran valor mantener esto pregunta, ya que el título es más genérico (no hace referencia a la respuesta, es decir: isset()).

    – Tom Auger

    10 de agosto de 2015 a las 17:24

  • Son duplicados claros y exactos. Admito que no pensé mucho en cuál debería ser el original, estaba en medio de otra cosa, hacer un vínculo entre los dos era el objetivo. Retrayendo mi VTC.

    – Palec

    10 de agosto de 2015 a las 19:09

  • Un duplicado exacto, marcado (en mi opinión erróneamente) como un duplicado de otra pregunta: ¿abreviatura de PHP para isset ()?

    – Palec

    10 de agosto de 2015 a las 19:11

avatar de usuario
PernoReloj

PHP 5.3 tiene una abreviatura ?: operador:

$foo = $bar ?: $baz;

que asigna $bar si no es un valor vacío (no sé cómo sería diferente en PHP de Perl), de lo contrario $bazy es lo mismo que esto en Perl y versiones anteriores de PHP:

$foo = $bar ? $bar : $baz;

Pero PHP no tiene un operador de asignación compuesto para esto (es decir, ningún equivalente al de Perl). ||=).

Además, PHP hará ruido si $bar no está configurado a menos que desactive los avisos. También hay una diferencia semántica entre isset() y empty(). El primero devuelve falso si la variable no existe, o se establece en NULL. Este último devuelve verdadero si no existe, o se establece en 0, '', false o NULL.

  • +1 Por presentarme otra gran característica de 5.3 que me estoy perdiendo en mis servidores RHEL5/PHP5.1.2.

    –Michael Berkowski

    12 de mayo de 2011 a las 2:10

  • Supongo que te refieres The first returns en vez de The second en tu penúltima oración.

    – Totó

    12 de mayo de 2011 a las 8:16

  • Tenga en cuenta que si su variable no está definida, PHP lanzará avisos al respecto. Esto, desafortunadamente, no es un reemplazo para $var = isset($var) ? $var : 'default value'; Dice eso en la respuesta … solo señalándolo nuevamente para cualquiera que lo hojee. 😀

    – brad

    02/06/2014 a las 15:00


  • ¿Es malo hacer $var = @$var?: ‘valor por defecto’; Si es así, ¿por qué? Dado que el único “error” podría ser que $var no está configurado, y que no nos importa si $var no está configurado…

    – Código mono

    13 de noviembre de 2015 a las 14:14

En PHP 7 finalmente tenemos una manera de hacer esto elegantemente. se llama el Operador coalescente nulo. Puedes usarlo así:

$name = $_GET['name'] ?? 'john doe';

Esto es equivalente a

$name = isset($_GET['name']) ? $_GET['name']:'john doe';

  • Yo argumentaría el operador de nave espacial tiene mérito también.

    – Mariano

    11 de junio de 2017 a las 5:41

  • Pensé que Mariano nos estaba tomando el pelo pero no, es una cosa. <=> y bastante preciso para arrancar!

    – HPWD

    14 de junio de 2018 a las 23:32

  • Tenga en cuenta que el operador coalescente nulo se comporta de manera diferente al operador condicional, ya que es específico de un null valor. Por ejemplo, si $_GET['name'] se establece en una cadena vacía, la primera línea devolvería una cadena vacía, pero podríamos devolver “john doe” usando $_GET['name'] ? $_GET['name'] : 'john doe'.

    – Vphantom

    20 mayo 2020 a las 18:33


  • @Mariano, sí, pero ¿cómo es relevante aquí el operador de la nave espacial?

    – Xsmael

    18 de junio de 2021 a las 10:17

avatar de usuario
barrena tom

¡Gracias por todas las excelentes respuestas!

Para cualquier otra persona que venga aquí en busca de una posible alternativa, aquí hay algunas funciones que ayudan a eliminar el tedio de este tipo de cosas.

function set_if_defined(&$var, $test){
    if (isset($test)){
        $var = $test;
        return true;
    } else {
        return false;
    }
}

function set_unless_defined(&$var, $default_var){
    if (! isset($var)){
        $var = $default_var;
        return true;
    } else {
        return false;
    }
}

function select_defined(){
    $l = func_num_args();
    $a = func_get_args();
    for ($i=0; $i<$l; $i++){
        if ($a[$i]) return $a[$i];
    }
}

Ejemplos:

// $foo ||= $bar;
set_unless_defined($foo, $bar);

//$foo = $baz || $bletch
$foo = select_defined($baz, $bletch);

Estoy seguro de que estos se pueden mejorar.

En PHP anterior a 7.*, se puede usar ?: para una variable indefinida que tiene errores suprimidos localmente con un @:

$foo = @$bar ?: $baz;

  • ¿No se emite un aviso con $bool ? $bool : "default" si $bool no esta definido?

    – BoltClock

    12 de mayo de 2011 a las 2:03


  • Claro, eso es lo mismo. Supuse que OP se refiere a isset($var) ? $var : DEFAULT. Pero parece que quiere evitarlos de todos modos.

    – mario

    12 de mayo de 2011 a las 2:05


avatar de usuario
Bassem Shahin

este es otro buen formato para el isset caso

isset($foo) || $foo= $bar;

otra forma simple y le dará más control ya que puede agregar más condiciones y asignar a otra variable al mismo tiempo

$foo = (isset($oData['foo']))?$bar['foo']:'default value';

Una posible solución: defaultFor()

A menos que tengamos una solución de fábrica (que de hecho es muy molesta), recomendaría el siguiente pequeño ayudante. Hace el trabajo en la mayoría de los casos:


    function defaultFor(&$x,$default=null) {
        if(!isset($x)) $x = $default;
    }

    //--------------------  Now you can do this: --------------

    defaultFor($a,"Jack");  // if $a is not set, it will be "Jack"
    defaultFor($x);         // no more notices for $x but keep it !isset

Espero que esto se acerque a lo que querías lograr. No le dará ningún aviso si lo usa con una variable inexistente, y es muy conveniente. Seguramente tiene un inconveniente: el valor predeterminado siempre se calcula de antemano, así que no lo use con nada pesado como segundo parámetro, como file_get_contents o algo así. En esos casos, es mejor issetting.

avatar de usuario
la mitad

Creo que en general hacer algo como esto:

$foo = $bar || $baz;

es una mala idea, a menos que $bar y $baz ambos son booleanos. Si no lo son:

$bar = 10;
$baz = 11;

entonces la pregunta es: ¿qué determina si algo es verdadero o falso? La mayoría de la gente probablemente esperaría que cero sea falso y que todo lo demás sea verdadero. Pero con algunos lenguajes (por ejemplo, Ruby), solo false y nil son falsos, lo que significa que ambos 0 y 1 seria verdad Debido a esta ambigüedad entre idiomas, creo que es mejor ser explícito en estos casos:

if ($bar !== 0) {
   $foo = $bar;
} else {
   $foo = $baz;
}

o:

$foo = $bar !== 0 ? $bar : $baz;

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad