web-dev-qa-db-fra.com

Comment pourrais-je ignorer des arguments optionnels dans un appel de fonction?

OK, j'ai totalement oublié comment ignorer les arguments en PHP.

Disons que j'ai:

function getData($name, $limit = '50', $page = '1') {
    ...
}

Comment appeler cette fonction pour que le paramètre central prenne la valeur par défaut (c'est-à-dire '50')?

getData('some name', '', '23');

Ce qui précède serait-il correct? Je n'arrive pas à faire en sorte que cela fonctionne.

77
Sebastian

Votre message est correct.

Malheureusement, si vous devez utiliser un paramètre facultatif à la fin de la liste, vous devez tout spécifier jusqu'à ce dernier paramètre. Généralement, si vous voulez mélanger et faire correspondre, vous leur donnez les valeurs par défaut de '' ou null et ne les utilisez pas dans la fonction si elles correspondent à cette valeur par défaut.

47
zombat

Il n'y a aucun moyen de "sauter" un argument autre que de spécifier une valeur par défaut telle que false ou null

Comme il manque un peu de sucre syntaxique à PHP, vous verrez souvent quelque chose comme ceci:

checkbox_field(array(
    'name' => 'some name',
    ....
));

Comme indiqué avec éloquence dans les commentaires, utilise des tableaux pour imiter des arguments nommés.

Cela donne une flexibilité ultime mais peut ne pas être nécessaire dans certains cas. À tout le moins, vous pouvez déplacer ce que vous pensez ne pas être attendu la plupart du temps à la fin de la liste des arguments.

36
Paolo Bergantino

Non, il n'est pas possible de sauter des arguments de cette façon. Vous pouvez omettre les arguments seulement s'ils sont à la fin de la liste des paramètres.

Il y avait une proposition officielle pour cela: https://wiki.php.net/rfc/skipparams , qui a été refusée. La page de proposition renvoie à d'autres SO questions sur ce sujet.

31
Cristik

Rien n'a changé en ce qui concerne le fait de pouvoir ignorer les arguments facultatifs. Cependant, pour une syntaxe correcte et pour pouvoir spécifier NULL pour les arguments que je veux ignorer, voici comment je procéderais:

define('DEFAULT_DATA_LIMIT', '50');
define('DEFAULT_DATA_PAGE', '1');

/**
 * getData
 * get a page of data 
 *
 * Parameters:
 *     name - (required) the name of data to obtain
 *     limit - (optional) send NULL to get the default limit: 50
 *     page - (optional) send NULL to get the default page: 1
 * Returns:
 *     a page of data as an array
 */

function getData($name, $limit = NULL, $page = NULL) {
    $limit = ($limit==NULL) ? DEFAULT_DATA_LIMIT : $limit;
    $page = ($page==NULL) ? DEFAULT_DATA_PAGE : $page;
    ...
}

Ceci peut être appelé ainsi: getData('some name',NULL,'23'); et toute personne appelant la fonction dans le futur n’a pas besoin de se souvenir des valeurs par défaut à chaque fois ni de la constante déclarée pour elles. 

5
Ibrahim Lawal

Vous ne pouvez pas ignorer les arguments mais vous pouvez utiliser des paramètres de tableau et vous devez définir un seul paramètre, qui est un tableau de paramètres.

function myfunction($array_param)
{
    echo $array_param['name'];
    echo $array_param['age'];
    .............
}

Et vous pouvez ajouter autant de paramètres que vous avez besoin, vous n'avez pas besoin de les définir. Lorsque vous appelez la fonction, vous définissez vos paramètres comme suit:

myfunction(array("name" => "Bob","age" => "18", .........));
2
Vlad Isoc

Pour tout paramètre ignoré (vous devez) aller avec le paramètre par défaut, pour être du côté sûr.

(Régler pour null où le paramètre par défaut est '' ou similaire ou vice versa vous mettra en difficulté ...)

2
Frank Nocke

Comme mentionné ci-dessus, vous ne pourrez pas ignorer les paramètres. J'ai écrit cette réponse pour fournir un addendum, qui était trop volumineux pour être placé dans un commentaire.

@Frank Nocke propose d’appeler la fonction avec ses paramètres par défaut, pour avoir par exemple

function a($b=0, $c=NULL, $d=''){ //...

tu devrais utiliser

$var = a(0, NULL, 'ddd'); 

ce qui revient fonctionnellement à omettre les deux premiers paramètres ($b et $c).

Il est difficile de savoir lesquelles sont les valeurs par défaut (0 est-il saisi pour fournir la valeur par défaut, ou est-ce important?).

Il existe également un risque que le problème des valeurs par défaut soit lié à une fonction externe (ou intégrée), lorsque les valeurs par défaut pourraient être modifiées par l'auteur de la fonction (ou de la méthode). Donc, si vous ne modifiez pas votre appel dans le programme, vous pouvez modifier son comportement par inadvertance.

Une solution de contournement pourrait consister à définir des constantes globales, telles que DEFAULT_A_B qui serait "la valeur par défaut du paramètre B de la fonction A" et les paramètres "omis" de cette façon:

$var = a(DEFAULT_A_B, DEFAULT_A_C, 'ddd');

Pour les classes, il est plus facile et plus élégant de définir des constantes de classe, car elles font partie de la portée globale, par exemple.

class MyObjectClass {
  const DEFAULT_A_B = 0;

  function a($b = self::DEFAULT_A_B){
    // method body
  }
} 
$obj = new MyObjectClass();
$var = $obj->a(MyObjectClass::DEFAULT_A_B); //etc.

Notez que cette constante par défaut est définie exactement une fois dans le code (il n'y a pas de valeur même dans la déclaration de méthode). Ainsi, en cas de modifications inattendues, vous fournirez toujours la fonction/méthode avec la valeur par défaut correcte.

La clarté de cette solution est bien entendu meilleure que de fournir des valeurs brutes par défaut (telles que NULL, 0 etc.) qui ne disent rien au lecteur.

(Je suis d'accord pour dire que l'appel comme $var = a(,,'ddd'); serait la meilleure option)

2
Voitcus

Comme indiqué précédemment , rien n'a changé . Attention, trop de paramètres (surtout ceux facultatifs) sont un indicateur puissant de l'odeur de code.

Peut-être que votre fonction en fait trop:

// first build context
$dataFetcher->setPage(1);
// $dataFetcher->setPageSize(50); // not used here
// then do the job
$dataFetcher->getData('some name');

Certains paramètres peuvent être regroupés de manière logique:

$pagination = new Pagination(1 /*, 50*/);
getData('some name', $pagination);
// Java coders will probably be familiar with this form:
getData('some name', new Pagination(1));

En dernier recours, vous pouvez toujours introduire un objet de paramètre ad-hoc :

$param = new GetDataParameter();
$param->setPage(1);
// $param->setPageSize(50); // not used here
getData($param);

(qui est juste une version glorifiée de la technique moins formelle parameter array )

Parfois, la raison même de rendre un paramètre facultatif est fausse. Dans cet exemple, $page est-il vraiment censé être optionnel? Sauvegarder quelques personnages fait-il vraiment une différence?

// dubious
// it is not obvious at first sight that a parameterless call to "getData()"
// returns only one page of data
function getData($page = 1);

// this makes more sense
function log($message, $timestamp = null /* current time by default */);
0
RandomSeed

Définir la limite sur null

function getData($name, $limit = null, $page = '1') {
    ...
}

et appeler à cette fonction

getData('some name', null, '23');

si vous voulez définir la limite, vous pouvez passer comme argument

getData('some name', 50, '23');
0
utreeworld

Cet extrait:


 fonction getData ($ name, $ options) {
 $ default = array (
 'limite' => 50, 
 'page' => 2, 
); $ args = array_merge ($ default, $ options); 
 print_r ($ args); 
 } 

 getData ('foo', array ()); 
 getData ('foo', array ('limit' => 2)); 
 getData ('foo', array ('limit' => 10, 'page' => 10)); 

La réponse est:


 Tableau 
 (
 [limite] => 50 
 [page] => 2 
) 
 Tableau 
 (
 [limite] => 2 
 [page] => 2 
) 
 Tableau 
 (
 [limite] => 10 
 [page] => 10 
) 

0
nobody0day

C'est une sorte de vieille question avec un certain nombre de réponses techniquement compétentes, mais elle appelle l'un des modèles de conception modernes de PHP: la programmation orientée objet. Au lieu d'injecter une collection de types de données scalaires primitifs, envisagez d'utiliser un "objet injecté" contenant toutes les données nécessaires à la fonction . http://php.net/manual/fr/language.types .intro.php

L'objet injecté peut avoir des routines de validation des propriétés, etc. Si l'instanciation et l'injection de données dans l'objet injecté sont incapables de passer toute la validation, le code peut lever une exception immédiatement et l'application peut éviter le processus fastidieux de traitement avec des données potentiellement incomplètes.

Nous pouvons dactylographier l'objet injecté pour détecter les erreurs avant le déploiement. Certaines des idées sont résumées dans cet article d’il ya quelques années.

https://www.experts-exchange.com/articles/18409/Using-Named-Parameters-in-PHP-Function-Calls.html

0
Ray Paseur

Voici ce que je ferais:

<?php

    function getData($name, $limit = '', $page = '1') {
            $limit = (EMPTY($limit)) ? 50 : $limit;
            $output = "name=$name&limit=$limit&page=$page";
            return $output;
    }

     echo getData('table');

    /* output name=table&limit=50&page=1 */

     echo getData('table',20);

    /* name=table&limit=20&page=1 */

    echo getData('table','',5);

    /* output name=table&limit=50&page=5 */

    function getData2($name, $limit = NULL, $page = '1') {
            $limit = (ISSET($limit)) ? $limit : 50;
            $output = "name=$name&limit=$limit&page=$page";
            return $output;
    }

    echo getData2('table');

    // /* output name=table&limit=50&page=1 */

    echo getData2('table',20);

    /* output name=table&limit=20&page=1 */

    echo getData2('table',NULL,3);

    /* output name=table&limit=50&page=3 */

?>

J'espère que cela aidera quelqu'un

0
Michael Eugene Yuen

Comme tout le monde l'a déjà dit, ce que vous voulez ne sera pas possible dans PHP sans l'ajout de lignes de code dans la fonction.

Mais vous pouvez placer ce morceau de code en haut d'une fonction pour obtenir votre fonctionnalité:

foreach((new ReflectionFunction(debug_backtrace()[0]["function"]))->getParameters() as $param) {
    if(empty(${$param->getName()}) && $param->isOptional())
        ${$param->getName()} = $param->getDefaultValue();
}

Donc, fondamentalement, avec debug_backtrace() je reçois le nom de la fonction dans lequel ce code est placé, pour créer ensuite un nouvel objet ReflectionFunction et passer en boucle avec tous les arguments de la fonction.

Dans la boucle, je vérifie simplement si l'argument de la fonction est empty() ET l'argument est "facultatif" (signifie qu'il a une valeur par défaut). Si oui, j'attribue simplement la valeur par défaut à l'argument.

Demo

0
Rizier123