Fonction PHP avec paramètres facultatifs

107

J'ai écrit une fonction PHP qui peut accepter 10 paramètres, mais seulement 2 sont nécessaires. Parfois, je veux définir le huitième paramètre, mais je ne veux pas taper des chaînes vides pour chacun des paramètres jusqu'à ce que j'atteigne le huitième.

Une idée que j'ai eue était de passer une fonction abstraite avec un tableau de paramètres qui la transmet à la fonction réelle.

Existe-t-il une meilleure façon de configurer la fonction afin que je puisse transmettre uniquement les paramètres que je veux?

user481826
la source
C'est étrange. Les fonctions intégrées dans php peuvent avoir des paramètres optionnels. Alors pourquoi ne pouvons-nous pas créer de telles fonctions?
Rodrigo
2
Notez que beaucoup de ces réponses sont DÉPASSÉES ... PHP prend désormais en charge les fonctions avec des listes d'arguments de longueur variable .
ashleedawg

Réponses:

62

Faites en sorte que la fonction prenne un paramètre: un tableau. Transmettez les paramètres réels en tant que valeurs dans le tableau.


Edit: le lien dans le commentaire de Pekka résume à peu près tout.

Matt Ball
la source
1
C'est étrange. Les fonctions intégrées dans php peuvent avoir des paramètres optionnels. Alors pourquoi ne pouvons-nous pas créer de telles fonctions?
Rodrigo
1
@Rodrigo il est absolument possible de définir des fonctions comme celles-ci. Ils sont cependant optionnels positionnels, ce qui est assez moche pour tout ce qui dépasse un seul paramètre facultatif.
Matt Ball
1
Ok, j'essayais avec [], maintenant je vois comment faire ici: stackoverflow.com/a/34869/1086511
Rodrigo
Il y a plus à faire que la simple suggestion «d'utiliser un tableau» - jetez un œil à la réponse de Walf à une question similaire et à l'exemple plus détaillé dans le même fil
DJDave
63

Ce que j'ai fait dans ce cas, c'est de passer un tableau, où la clé est le nom du paramètre et la valeur est la valeur.

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

function func($required, $requiredTwo, $optional) {
  if(isset($optional["param2"])) {
    doWork();
  }
}
Rabbott
la source
Pour votre exemple, $ optional n'aurait-il pas besoin d'être défini global dans la fonction?
user481826
1
global? non..? Vous créez ce tableau avant d'appeler la fonction et vous le transmettez. Mon code est un exemple de description de Matt Balls de ce qui doit être fait.
Rabbott
Il y a plus à faire que les suggestions «utiliser un tableau» - jetez un œil à la réponse de Walf à une question similaire et à l'exemple plus détaillé dans le même fil
DJDave
45

Pour accomplir ce que vous voulez, utilisez un tableau comme l'a dit Rabbot (bien que cela puisse devenir difficile à documenter / maintenir s'il est utilisé de manière excessive). Ou utilisez simplement les arguments optionnels traditionnels.

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

Cependant, je trouve généralement que lorsque je commence à écrire une fonction / méthode avec autant d'arguments - le plus souvent, c'est une odeur de code, et peut être re-factorisée / abstraite en quelque chose de beaucoup plus propre.

//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
la source
En 2010, des notions telles que «odeur de code», «refactoring» ou «maintenance de code» n'étaient pas populaires dans notre communauté. Vous avez eu une étape avant la plupart d'entre nous :)
Billal Begueradj
15

Dans PHP 5.6 et versions ultérieures, les listes d'arguments peuvent inclure le jeton ... pour indiquer que la fonction accepte un nombre variable d'arguments. Les arguments seront passés dans la variable donnée sous forme de tableau; par exemple:

Exemple d'utilisation de ... pour accéder aux arguments de variable

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

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

L'exemple ci-dessus affichera:

10

Liste d'arguments de longueur variable Documentation PHP

Mentos1386
la source
Cette réponse mérite plus de points. Ne convient pas à mon scénario de cas spécifique mais de bonnes informations et simples à comprendre. PHP 7.3 arrive bientôt! 5.6 et 7 sont EOL.
AdheneManx
12

Vous pouvez simplement définir la valeur par défaut sur null.

<?php
function functionName($value, $value2 = null) {
// do stuff
}
Blake Stevenson
la source
2
La meilleure réponse, mais veuillez la remplacer nullpar les non-bits du type de date. par exemple array()pour les tableaux
Mohamed hesham
Merci ... C'est ce que je cherchais
Davide De Maestri
12

REMARQUE: Ceci est une ancienne réponse, pour PHP 5.5 et inférieur. PHP 5.6+ prend en charge les arguments par défaut

En PHP 5.5 et inférieur, vous pouvez y parvenir en utilisant l'une de ces 2 méthodes:

  • en utilisant func_num_args () et func_get_arg () ;
  • en utilisant des arguments NULL;

Comment utiliser

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

Je préfère la deuxième méthode car elle est propre et facile à comprendre, mais parfois vous aurez besoin de la première méthode.

Daniel Loureiro
la source
1
Vous avez besoin du double "=" ici ou toutes les expressions renverront vrai. De plus, les expressions du 2ème exemple renverront toujours true car une variable est toujours égale à elle-même.
chuckieDub
bon point, mais cela fonctionne réellement. En PHP, ce code $x = null; if ($x) echo "true"; else echo "false";affichera "false", même si le $ x var a une valeur ("null" dans ce code). De plus, dans les deux méthodes, nous utilisons l'opérateur ternaire, il est donc correct d'utiliser un seul "=". Si vous testez avec method(); method(1); method(1, 2);, alors le premier appel associera arg1 et arg2 aux valeurs par défaut, le second appel associera le second arg à la valeur par défaut et "1" pour le premier argument. Le dernier appel n'associera pas les valeurs par défaut.
Daniel Loureiro
1
function method_2 ($ arg1 = "default_value_fot_arg1", $ arg2 = "default_value_fot_arg2") {donc php traite des trucs de paramètres et vous pouvez également passer null comme paramètre (pourquoi les gens utilisent null je ne sais pas)
nerkn
1
@nerkn, vous avez raison, PHP prend actuellement en charge les arguments par défaut. Lol, je me souviens quand nous avons dû faire beaucoup de contournements pour réaliser des choses simples. Bon temps: P Vous pouvez toujours voir ces approches dans les anciens codes (pré-5.5), bien que.
Daniel Loureiro
4

Je pense que vous pouvez également utiliser des objets comme paramètres de transport.

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

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

Bien sûr, vous devez définir les valeurs par défaut pour "optParam8" et "optParam2" dans cette fonction, dans les autres cas, vous obtiendrez "Remarque: propriété non définie: stdClass :: $ optParam2"

Si vous utilisez des tableaux comme paramètres de fonction, j'aime cette façon de définir les valeurs par défaut:

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
la source
2

Si seulement deux valeurs sont nécessaires pour créer l'objet avec un état valide, vous pouvez simplement supprimer tous les autres arguments facultatifs et leur fournir des setters (sauf si vous ne voulez pas qu'ils soient modifiés à l'exécution). Ensuite, instanciez simplement l'objet avec les deux arguments requis et définissez les autres selon les besoins via le setter.

Lectures complémentaires

Gordon
la source
2

Je sais que c'est un ancien message, mais j'avais un problème comme l'OP et c'est ce que j'ai proposé.

Exemple de tableau que vous pourriez passer. Vous pouvez le commander à nouveau si une commande particulière était requise, mais pour cette question, cela fera ce qui est demandé.

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

Ceci est gérable, facile à lire et les points d'extraction de données peuvent être ajoutés et supprimés à un moment donné n'importe où dans le codage et évitent toujours une réécriture massive. J'ai utilisé des clés entières pour correspondre à la question originale OP, mais les clés de chaîne pourraient être utilisées tout aussi facilement. En fait pour la lisibilité je le conseillerais.

Collez-le dans un fichier externe pour plus de facilité

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

mettez ceci au début si le fichier.

$argument_set = array(); 

Utilisez-les simplement pour attribuer le prochain élément de données, utilisez la numérotation / la dénomination en fonction de la provenance des données.

$argument_set[1][] = $some_variable; 

Et enfin passer le tableau

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

Vous pouvez créer une fonction régulière, puis ajouter vos variables facultatives en leur donnant une valeur Null par défaut.

Un Null est toujours une valeur, si vous n'appelez pas la fonction avec une valeur pour cette variable, elle ne sera pas vide donc pas d'erreur.

Antoine Serry
la source
2
Pouvez-vous expliquer tout cela plus en détail? Le code donné est syntaxiquement invalide, car les noms de variables ne peuvent pas commencer par un nombre
Nico Haase
0

Si vous ne passez généralement que la 8ème valeur, vous pouvez réorganiser vos paramètres afin que ce soit le premier. Il vous suffit de spécifier les paramètres jusqu'au dernier que vous souhaitez définir.

Si vous utilisez des valeurs différentes, vous avez 2 options.

La première consisterait à créer un ensemble de fonctions wrapper qui prennent différents paramètres et définissent les valeurs par défaut sur les autres. Ceci est utile si vous n'utilisez que quelques combinaisons, mais peut rapidement devenir très compliqué.

L'autre option est de passer un tableau où les clés sont les noms des paramètres. Vous pouvez alors simplement vérifier s'il y a une valeur dans le tableau avec une clé, et sinon utiliser la valeur par défaut. Mais encore une fois, cela peut devenir compliqué et ajouter beaucoup de code supplémentaire si vous avez beaucoup de paramètres.

Alan Geleynse
la source
0

PHP autorise les arguments par défaut ( lien ). Dans votre cas, vous pouvez définir tous les paramètres de 3 à 8 comme NULL ou comme une chaîne vide "" en fonction de votre code de fonction. De cette manière, vous pouvez appeler la fonction uniquement en utilisant les deux premiers paramètres.

Par exemple:

<?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
la source
Idée intéressante ... mais votre proposition ne résout pas le problème. En fait, si vous ajoutez des informations sur l'argument en écho (par exemple en utilisant echo " this is arg3: " . $arg3;, etc., vous verrez que l'appel par exemple yourFunction(3, 2, $arg8=5);imprimera 32 this is arg3: 5. Le problème est que la position du paramètre compte toujours lors du passage de paramètres optionnels dans PHP ... noms de paramètres ne suffisent pas pour mapper les valeurs des paramètres aux noms des paramètres.
mastropi
0

Définissez simplement Null pour ignorer les paramètres que vous ne souhaitez pas utiliser, puis définissez le paramètre nécessaire en fonction de la position.

 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
la source
-4
func( "1", "2", default, default, default, default, default, "eight" );
Flinsch
la source
1
Ce n'est pas du PHP valide. defaultest un mot - clé en PHP .
Pang