Função PHP com parâmetros opcionais


107

Eu escrevi uma função PHP que pode aceitar 10 parâmetros, mas apenas 2 são necessários. Às vezes, quero definir o oitavo parâmetro, mas não quero digitar strings vazias para cada um dos parâmetros até chegar ao oitavo.

Uma ideia que tive foi passar uma função abstrata com um array de parâmetros que a passa para a função real.

Existe uma maneira melhor de configurar a função para que eu possa passar apenas os parâmetros que desejo?



Isso é estranho. As funções integradas no php podem ter parâmetros opcionais. Então, por que não podemos construir funções como essa?
Rodrigo

2
Note que muitas dessas respostas estão DESATIVADAS ... PHP agora suporta funções com listas de argumentos de comprimento variável .
ashleedawg

Respostas:


62

Faça com que a função tenha um parâmetro: um array. Passe os parâmetros reais como valores na matriz.


Editar: o link no comentário de Pekka resume tudo.


1
Isso é estranho. As funções integradas no php podem ter parâmetros opcionais. Então, por que não podemos construir funções como essa?
Rodrigo

1
@Rodrigo é absolutamente factível definir funções como essas. Eles são opcionais posicionais, o que é muito ruim para qualquer coisa além de um único parâmetro opcional.
Matt Ball

1
Ok, estava tentando com [], agora vejo como fazer aqui: stackoverflow.com/a/34869/1086511
Rodrigo

Há mais que pode ser feito do que apenas a sugestão de "usar um array" - dê uma olhada na resposta de Walf a uma pergunta semelhante e o exemplo mais detalhado no mesmo tópico
DJDave

63

O que fiz neste caso foi passar um array, onde a chave é o nome do parâmetro e o valor é o valor.

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

function func($required, $requiredTwo, $optional) {
  if(isset($optional["param2"])) {
    doWork();
  }
}

Para seu exemplo, $ optional não precisaria ser definido como global dentro da função?
user481826 de

1
global? não..? Você cria esse array antes de chamar a função e passa-o. Meu código é um exemplo da descrição de Matt Balls do que deve ser feito.
Rabbott,

Há mais que pode ser feito do que apenas as sugestões de "usar uma matriz" - dê uma olhada na resposta de Walf a uma pergunta semelhante e no exemplo mais aprofundado no mesmo tópico
DJDave

45

Para realizar o que você deseja, use um array como o Rabbot disse (embora isso possa se tornar uma dor de documentar / manter se usado excessivamente). Ou apenas use os argumentos opcionais tradicionais.

//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');

No entanto, eu normalmente acho que quando eu começo a escrever uma função / método com tantos argumentos - na maioria das vezes é um cheiro de código e pode ser refeito / abstraído em algo muito mais limpo.

//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');

Em 2010, noções como 'cheiro de código', 'refatoração' ou 'manutenção de código' não eram populares em nossa comunidade. Você deu um passo antes da maioria de nós :)
Billal Begueradj

15

No PHP 5.6 e posterior, as listas de argumentos podem incluir o token ... para denotar que a função aceita um número variável de argumentos. Os argumentos serão passados ​​para a variável fornecida como um array; por exemplo:

Exemplo usando ... para acessar argumentos variáveis

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

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

O exemplo acima produzirá:

10

O argumento de comprimento variável lista a documentação do PHP


Esta resposta merece mais pontos. Não é adequado para o meu cenário de caso específico, mas é uma boa informação e simples de entender. PHP 7.3 chegará em breve! 5,6 e 7 são EOL.
AdheneManx

12

Você pode apenas definir o valor padrão como nulo.

<?php
function functionName($value, $value2 = null) {
// do stuff
}

2
A melhor resposta, mas substitua nullpelos não bits do tipo de data. por exemplo, array()para matrizes
Mohamed hesham,

Obrigado ... Isso é o que eu estava procurando
Davide De Maestri

12

NOTA: Esta é uma resposta antiga, para PHP 5.5 e inferior. PHP 5.6+ suporta argumentos padrão

No PHP 5.5 e inferior, você pode fazer isso usando um destes 2 métodos:

  • usando as funções func_num_args () e func_get_arg () ;
  • usando argumentos NULL;

Como usar

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

Eu prefiro o segundo método porque é claro e fácil de entender, mas às vezes você pode precisar do primeiro método.


1
Você precisa do duplo "=" aqui ou todas as expressões retornarão verdadeiras. Além disso, as expressões no segundo exemplo sempre retornarão true porque uma variável é sempre igual a si mesma.
chuckieDub

bom ponto, mas isso realmente funciona. Em PHP, este código $x = null; if ($x) echo "true"; else echo "false";irá imprimir "false", mesmo se $ x var tiver um valor ("null" neste código). Além disso, em ambos os métodos estamos usando o operador ternário, então é correto usar apenas um "=". Se você testar com method(); method(1); method(1, 2);, a primeira chamada associará arg1 e arg2 aos valores padrão, a segunda chamada associará o segundo arg ao valor padrão e "1" ao primeiro arg. A última chamada não associará os valores padrão.
Daniel Loureiro

1
function method_2 ($ arg1 = "default_value_fot_arg1", $ arg2 = "default_value_fot_arg2") {então php lida com coisas de parâmetro e também você pode passar null como parâmetro (porque as pessoas usam null eu não sei)
nerkn

1
@nerkn, você está certo, o PHP atualmente suporta argumentos padrão. Lol, eu me lembro quando precisávamos fazer várias soluções alternativas para conseguir coisas simples. Bons tempos: P Você ainda pode ver essas abordagens em códigos antigos (pré-5.5), embora.
Daniel Loureiro

4

Acho que você pode usar objetos como params-transportes também.

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

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

Claro, você deve definir os valores padrão para "optParam8" e "optParam2" nesta função, em outro caso você obterá "Aviso: Propriedade indefinida: stdClass :: $ optParam2"

Se estiver usando arrays como parâmetros de função, gosto desta maneira de definir os valores padrão:

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']."!";
}

2

Se apenas dois valores são necessários para criar o objeto com um estado válido, você pode simplesmente remover todos os outros argumentos opcionais e fornecer setters para eles (a menos que você não queira que eles sejam alterados no tempo de execução). Em seguida, instancie o objeto com os dois argumentos necessários e defina os outros conforme necessário por meio do setter.

Leitura adicional


2

Eu sei que este é um post antigo, mas eu estava tendo um problema como o OP e foi isso que eu descobri.

Exemplo de array que você poderia passar. Você poderia solicitar novamente se um pedido específico fosse necessário, mas para esta pergunta, fará o que for solicitado.

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

Isso é gerenciável, fácil de ler e os pontos de extração de dados podem ser adicionados e removidos em qualquer momento da codificação e ainda evitar uma reescrita em massa. Usei chaves inteiras para calcular a pergunta original do OP, mas as chaves de string podem ser usadas com a mesma facilidade. Na verdade, para facilitar a leitura, eu o aconselharia.

Cole isso em um arquivo externo para facilitar

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

coloque isso no início se o arquivo.

$argument_set = array(); 

Apenas use-os para atribuir a próxima parte de dados, use numeração / nomeação de acordo com a origem dos dados.

$argument_set[1][] = $some_variable; 

E finalmente passe o array

unknown_number_arguments($argument_set);

1
function yourFunction($var1, $var2, $optional = Null){
   ... code
}

Você pode fazer uma função regular e, em seguida, adicionar suas variáveis ​​opcionais, dando-lhes um valor nulo padrão.

Um Null ainda é um valor, se você não chamar a função com um valor para aquela variável, ela não ficará vazia, então sem erro.


2
Você pode explicar tudo isso melhor? O código fornecido é sintaticamente inválido, pois os nomes das variáveis ​​não podem começar com um número
Nico Haase

0

Se você costuma passar apenas o 8º valor, pode reordenar seus parâmetros para que seja o primeiro. Você só precisa especificar os parâmetros até o último que deseja definir.

Se estiver usando valores diferentes, você terá 2 opções.

Uma seria criar um conjunto de funções de invólucro que usem parâmetros diferentes e definam os padrões nos outros. Isso é útil se você usar apenas algumas combinações, mas pode ficar muito confuso rapidamente.

A outra opção é passar um array onde as chaves são os nomes dos parâmetros. Você pode então apenas verificar se há um valor na matriz com uma chave e, se não, usar o padrão. Mas, novamente, isso pode ficar confuso e adicionar muito código extra se você tiver muitos parâmetros.


0

PHP permite argumentos padrão ( link ). No seu caso, você pode definir todos os parâmetros de 3 a 8 como NULL ou como uma string vazia "" dependendo do código da função. Dessa forma, você pode chamar a função usando apenas os dois primeiros parâmetros.

Por exemplo:

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

Ideia interessante ... porém sua proposta não resolve o problema. Na verdade, se você adicionar informações sobre qual argumento está sendo ecoado (por exemplo, usando echo " this is arg3: " . $arg3;, etc., você verá que chamar eg yourFunction(3, 2, $arg8=5);irá imprimir 32 this is arg3: 5. O problema é que a posição do parâmetro ainda importa ao passar parâmetros opcionais em PHP ... nomes de parâmetro não são suficientes para mapear os valores dos parâmetros para os nomes dos parâmetros.
mastropi

0

Basta definir Null para ignorar os parâmetros que você não deseja usar e, em seguida, definir o parâmetro necessário de acordo com a posição.

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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.