Función PHP con parámetros opcionales

107

Escribí una función PHP que puede aceptar 10 parámetros, pero solo se requieren 2. A veces, quiero definir el octavo parámetro, pero no quiero escribir cadenas vacías para cada uno de los parámetros hasta que llegue al octavo.

Una idea que tuve fue pasar una función abstraída con una matriz de parámetros que la pasa junto a la función real.

¿Existe una mejor manera de configurar la función para que pueda pasar solo los parámetros que quiero?

user481826
fuente
Eso es extraño. Las funciones integradas en php pueden tener parámetros opcionales. Entonces, ¿por qué no podemos construir funciones como esa?
Rodrigo
2
Tenga en cuenta que muchas de estas respuestas están ACTUALIZADAS ... PHP ahora admite funciones con listas de argumentos de longitud variable .
ashleedawg

Respuestas:

62

Haga que la función tome un parámetro: una matriz. Pase los parámetros reales como valores en la matriz.


Editar: el enlace en el comentario de Pekka casi lo resume.

Matt Ball
fuente
1
Eso es extraño. Las funciones integradas en php pueden tener parámetros opcionales. Entonces, ¿por qué no podemos construir funciones como esa?
Rodrigo
1
@Rodrigo es absolutamente posible definir funciones como esas. Sin embargo, son posicionales opcionales, lo que es bastante pésimo para cualquier cosa más allá de un solo parámetro opcional.
Matt Ball
1
Ok, estaba intentando con [], ahora veo cómo hacerlo aquí: stackoverflow.com/a/34869/1086511
Rodrigo
Se puede hacer más que solo la sugerencia de "usar una matriz": eche un vistazo a la respuesta de Walf a una pregunta similar y el ejemplo más detallado en el mismo hilo
DJDave
63

Lo que he hecho en este caso es pasar una matriz, donde la clave es el nombre del parámetro y el valor es el valor.

$optional = array(
  "param" => $param1,
  "param2" => $param2
);

function func($required, $requiredTwo, $optional) {
  if(isset($optional["param2"])) {
    doWork();
  }
}
Rabbott
fuente
Para su ejemplo, ¿no sería necesario establecer $ opcional como global dentro de la función?
user481826
1
¿global? No..? Creas esa matriz antes de llamar a la función y la pasas. Mi código es un ejemplo de la descripción de Matt Balls de lo que se debe hacer.
Rabbott
Se puede hacer más que solo las sugerencias de "usar una matriz": eche un vistazo a la respuesta de Walf a una pregunta similar y al ejemplo más detallado en el mismo hilo
DJDave
45

Para lograr lo que desea, use una matriz como dijo Rabbot (aunque esto puede convertirse en una molestia para documentar / mantener si se usa en exceso). O simplemente use los argumentos opcionales tradicionales.

//My function with tons of optional params
function my_func($req_a, $req_b, $opt_a = NULL, $opt_b = NULL, $opt_c = NULL)
{
  //Do stuff
}
my_func('Hi', 'World', null, null, 'Red');

Sin embargo, generalmente encuentro que cuando comienzo a escribir una función / método con tantos argumentos, la mayoría de las veces es un olor a código y se puede refactorizar / abstraer en algo mucho más limpio.

//Specialization of my_func - assuming my_func itself cannot be refactored
function my_color_func($reg_a, $reg_b, $opt = 'Red')
{
  return my_func($reg_a, $reg_b, null, null, $opt);
}
my_color_func('Hi', 'World');
my_color_func('Hello', 'Universe', 'Green');
Kayla Rose
fuente
En 2010, nociones como "olor de código", "refactorización" o "mantenimiento de código" no eran populares en nuestra comunidad. Tenías un paso antes que la mayoría de nosotros :)
Billal Begueradj
15

En PHP 5.6 y posterior, las listas de argumentos pueden incluir el símbolo ... para indicar que la función acepta un número variable de argumentos. Los argumentos se pasarán a la variable dada como una matriz; por ejemplo:

Ejemplo usando ... para acceder a argumentos variables

<?php
function sum(...$numbers) {
    $acc = 0;
    foreach ($numbers as $n) {
        $acc += $n;
    }
    return $acc;
}

echo sum(1, 2, 3, 4);
?>

El ejemplo anterior dará como resultado:

10

Listas de argumentos de longitud variable Documentación PHP

Mentos1386
fuente
Esta respuesta merece más puntos. No es adecuado para el escenario de mi caso específico, pero es buena información y fácil de entender. PHP 7.3 estará disponible en breve. 5.6 y 7 son EOL.
AdheneManx
12

Puede establecer el valor predeterminado en nulo.

<?php
function functionName($value, $value2 = null) {
// do stuff
}
Blake Stevenson
fuente
2
La mejor respuesta, pero reemplácela nullcon los que no sean bits del tipo de fecha. por ejemplo array()para matrices
Mohamed Hesham
Gracias ... Esto es lo que estaba buscando
Davide De Maestri
12

NOTA: Esta es una respuesta antigua, para PHP 5.5 y versiones anteriores. PHP 5.6+ admite argumentos predeterminados

En PHP 5.5 y versiones anteriores, puede lograr esto utilizando uno de estos 2 métodos:

  • usando las funciones func_num_args () y func_get_arg () ;
  • usando argumentos NULL;

Cómo utilizar

function method_1()
{
  $arg1 = (func_num_args() >= 1)? func_get_arg(0): "default_value_for_arg1";
  $arg2 = (func_num_args() >= 2)? func_get_arg(1): "default_value_for_arg2";
}

function method_2($arg1 = null, $arg2 = null)
{
  $arg1 = $arg1? $arg1: "default_value_for_arg1";
  $arg2 = $arg2? $arg2: "default_value_for_arg2";
}

Prefiero el segundo método porque es limpio y fácil de entender, pero a veces es posible que necesite el primer método.

Daniel Loureiro
fuente
1
Necesita el doble "=" aquí o todas las expresiones devolverán verdadero. Además, las expresiones del segundo ejemplo siempre devolverán verdadero porque una variable siempre es igual a sí misma.
chuckieDub
buen punto, pero esto realmente funciona. En PHP, este código $x = null; if ($x) echo "true"; else echo "false";imprimirá "falso", incluso si $ x var tiene un valor ("nulo" en este código). Además, en ambos métodos estamos usando el operador ternario, por lo que es correcto usar solo un "=". Si prueba con method(); method(1); method(1, 2);, la primera llamada asociará arg1 y arg2 con los valores predeterminados, la segunda llamada asociará el segundo arg con el valor predeterminado y "1" para el primer argumento. La última llamada no asociará valores predeterminados.
Daniel Loureiro
1
function method_2 ($ arg1 = "default_value_fot_arg1", $ arg2 = "default_value_fot_arg2") {entonces php se ocupa de los parámetros y también puede pasar null como parámetro (por qué la gente usa null, no lo sé)
nerkn
1
@nerkn, tienes razón, PHP actualmente admite argumentos predeterminados. Lol, recuerdo cuando necesitábamos hacer muchas soluciones para lograr cosas simples. Buenos tiempos: P Aún puede ver esos enfoques en códigos antiguos (anteriores a 5.5), aunque.
Daniel Loureiro
4

Creo que también puedes usar objetos como params-transportes.

$myParam = new stdClass();
$myParam->optParam2 = 'something';
$myParam->optParam8 = 3;
theFunction($myParam);

function theFunction($fparam){      
  return "I got ".$fparam->optParam8." of ".$fparam->optParam2." received!";
}

Por supuesto, debe establecer valores predeterminados para "optParam8" y "optParam2" en esta función, en otro caso obtendrá "Notice: Undefined property: stdClass :: $ optParam2"

Si utilizo matrices como parámetros de función, me gusta de esta manera establecer valores predeterminados:

function theFunction($fparam){
   $default = array(
      'opt1' => 'nothing',
      'opt2' => 1
   );
   if(is_array($fparam)){
      $fparam = array_merge($default, $fparam);
   }else{
      $fparam = $default;
   }
   //now, the default values are overwritten by these passed by $fparam
   return "I received ".$fparam['opt1']." and ".$fparam['opt2']."!";
}
psad
fuente
2

Si solo se requieren dos valores para crear el objeto con un estado válido, simplemente puede eliminar todos los demás argumentos opcionales y proporcionarles definidores (a menos que no desee que cambien en tiempo de ejecución). Luego, simplemente cree una instancia del objeto con los dos argumentos requeridos y configure los demás según sea necesario a través del establecedor.

Otras lecturas

Gordon
fuente
2

Sé que esta es una publicación antigua, pero estaba teniendo un problema como el OP y esto es lo que se me ocurrió.

Ejemplo de matriz que podría pasar. Puede volver a pedir esto si se requiere un pedido en particular, pero para esta pregunta, esto hará lo que se le pide.

$argument_set = array (8 => 'lots', 5 => 'of', 1 => 'data', 2 => 'here');

Esto es manejable, fácil de leer y los puntos de extracción de datos se pueden agregar y eliminar en cualquier momento en cualquier lugar de la codificación y aún así evitar una reescritura masiva. Usé claves enteras para coincidir con la pregunta original de OP, pero las claves de cadena se podrían usar con la misma facilidad. De hecho, por legibilidad, lo recomendaría.

Pegue esto en un archivo externo para mayor facilidad

function unknown_number_arguments($argument_set) {

    foreach ($argument_set as $key => $value) {

        # create a switch with all the cases you need. as you loop the array 
        # keys only your submitted $keys values will be found with the switch. 
        switch ($key) {
            case 1:
                # do stuff with $value
                break;
            case 2:
                # do stuff with $value;
                break;
            case 3:
                # key 3 omitted, this wont execute 
                break;
            case 5:
                # do stuff with $value;
                break;
            case 8:
                # do stuff with $value;
                break;
            default:
                # no match from the array, do error logging?
                break;
        }
    }
return;
}

ponga esto al principio si el archivo.

$argument_set = array(); 

Solo utilícelos para asignar el siguiente fragmento de uso de datos / numeración de acuerdo con el lugar de donde provienen los datos.

$argument_set[1][] = $some_variable; 

Y finalmente pasa la matriz

unknown_number_arguments($argument_set);
Chris
fuente
1
function yourFunction($var1, $var2, $optional = Null){
   ... code
}

Puede hacer una función regular y luego agregar sus variables opcionales dándoles un valor Nulo predeterminado.

Un nulo sigue siendo un valor, si no llama a la función con un valor para esa variable, no estará vacía, por lo que no hay error.

antoine serry
fuente
2
¿Puedes explicar todo eso más? El código proporcionado no es sintácticamente inválido, ya que los nombres de las variables no pueden comenzar con un número
Nico Haase
0

Si normalmente solo pasa el octavo valor, puede reordenar sus parámetros para que sea el primero. Solo necesita especificar los parámetros hasta el último que desea configurar.

Si está utilizando valores diferentes, tiene 2 opciones.

Una sería crear un conjunto de funciones contenedoras que tomen diferentes parámetros y establezcan los valores predeterminados de los demás. Esto es útil si solo usa algunas combinaciones, pero puede complicarse mucho rápidamente.

La otra opción es pasar una matriz donde las claves son los nombres de los parámetros. Luego, puede verificar si hay un valor en la matriz con una clave y, si no, usar el predeterminado. Pero nuevamente, esto puede complicarse y agregar mucho código extra si tiene muchos parámetros.

Alan Geleynse
fuente
0

PHP permite argumentos predeterminados ( enlace ). En su caso, podría definir todos los parámetros del 3 al 8 como NULL o como una cadena vacía "" dependiendo de su código de función. De esta manera, puede llamar a la función solo usando los dos primeros parámetros.

Por ejemplo:

<?php
  function yourFunction($arg1, $arg2, $arg3=NULL, $arg4=NULL, $arg5=NULL, $arg6=NULL, $arg7=NULL, $arg8=NULL){
echo $arg1;
echo $arg2;
if(isset($arg3)){echo $arg3;}
# other similar statements for $arg4, ...., $arg5
if(isset($arg8)){echo $arg8;}
}
Andrés Luna
fuente
Interesante idea ... sin embargo tu propuesta no resuelve el problema. De hecho, si agrega información sobre qué argumento se repite (por ejemplo echo " this is arg3: " . $arg3;, usando , etc., verá que llamar, por ejemplo, yourFunction(3, 2, $arg8=5);se imprimirá 32 this is arg3: 5. El problema es que la posición del parámetro sigue siendo importante cuando se pasan parámetros opcionales en PHP ... nombres de parámetros no son suficientes para asignar valores de parámetros a nombres de parámetros.
mastropi
0

Simplemente configure Null para ignorar los parámetros que no desea usar y luego configure el parámetro necesario según la posición.

 function myFunc($p1,$p2,$p3=Null,$p4=Null,$p5=Null,$p6=Null,$p7=Null,$p8=Null){
    for ($i=1; $i<9; $i++){
        $varName = "p$i";
        if (isset($$varName)){
            echo $varName." = ".$$varName."<br>\n";
        }
    }
}   

myFunc( "1", "2", Null, Null, Null, Null, Null, "eight" );
FERNANDO BARAZZETTI
fuente
-4
func( "1", "2", default, default, default, default, default, "eight" );
Flinsch
fuente
1
Esto no es PHP válido. defaultes una palabra clave en PHP .
Pang