Funzione PHP con parametri opzionali


107

Ho scritto una funzione PHP che può accettare 10 parametri, ma solo 2 sono necessari. A volte, voglio definire l'ottavo parametro, ma non voglio digitare stringhe vuote per ciascuno dei parametri fino a quando non raggiungo l'ottavo.

Un'idea che avevo era quella di passare una funzione astratta con un array di parametri che la passasse alla funzione reale.

C'è un modo migliore per impostare la funzione in modo da poter passare solo i parametri che voglio?



È strano. Le funzioni integrate in php possono avere parametri opzionali. Allora perché non possiamo costruire funzioni del genere?
Rodrigo

2
Notare che molte di queste risposte sono obsolete ... PHP ora supporta funzioni con elenchi di argomenti di lunghezza variabile .
ashleedawg

Risposte:


62

Fai in modo che la funzione prenda un parametro: un array. Passa i parametri effettivi come valori nell'array.


Modifica: il collegamento nel commento di Pekka lo riassume quasi.


1
È strano. Le funzioni integrate in php possono avere parametri opzionali. Allora perché non possiamo costruire funzioni del genere?
Rodrigo

1
@Rodrigo è assolutamente fattibile definire funzioni come quelle. Sono comunque opzionali posizionali, il che è piuttosto scadente per qualsiasi cosa oltre un singolo parametro opzionale.
Matt Ball

1
Ok, stavo provando con [], ora vedo come farlo qui: stackoverflow.com/a/34869/1086511
Rodrigo

C'è di più che si può fare che solo il suggerimento "usa un array" - dai un'occhiata alla risposta di Walf a una domanda simile e all'esempio più approfondito nello stesso thread
DJDave

63

Quello che ho fatto in questo caso è passare un array, dove la chiave è il nome del parametro e il valore è il valore.

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

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

Per il tuo esempio, $ optional non dovrebbe essere impostato come globale all'interno della funzione?
user481826

1
globale? no..? Crei quell'array prima di chiamare la funzione e lo passi. Il mio codice è un esempio della descrizione di Matt Balls di ciò che dovrebbe essere fatto.
Rabbott

C'è di più che si può fare che solo i suggerimenti "usa un array" - dai un'occhiata alla risposta di Walf a una domanda simile e all'esempio più approfondito nello stesso thread
DJDave

45

Per ottenere ciò che vuoi, usa un array come ha detto Rabbot (anche se questo può diventare un problema da documentare / mantenere se usato eccessivamente). Oppure usa semplicemente i tradizionali argomenti opzionali.

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

Tuttavia, di solito trovo che quando inizio a scrivere una funzione / metodo con così tanti argomenti, il più delle volte si tratta di un odore di codice e può essere ri-fattorizzato / astratto in qualcosa di molto più pulito.

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

Nel 2010, nozioni come "odore di codice", "refactoring" o "manutenzione del codice" non erano popolari nella nostra comunità. Hai fatto un passo prima della maggior parte di noi :)
Billal Begueradj

15

In PHP 5.6 e versioni successive, gli elenchi di argomenti possono includere il token ... per indicare che la funzione accetta un numero variabile di argomenti. Gli argomenti verranno passati nella variabile data come un array; per esempio:

Esempio Utilizzo di ... per accedere agli argomenti delle variabili

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

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

L'esempio precedente produrrà:

10

L'argomento a lunghezza variabile elenca la documentazione PHP


Questa risposta merita più punti. Non adatto al mio caso specifico, ma buone informazioni e semplici da capire. PHP 7.3 arriverà a breve! 5.6 e 7 sono EOL.
AdheneManx

12

Puoi semplicemente impostare il valore predefinito su null.

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

2
La risposta migliore, ma sostituisci nullcon i non bit del tipo di data. ad esempio array()per gli array
Mohamed hesham

Grazie ... Questo è quello che cercavo
Davide De Maestri

12

NOTA: questa è una vecchia risposta, per PHP 5.5 e versioni precedenti. PHP 5.6+ supporta gli argomenti predefiniti

In PHP 5.5 e versioni precedenti, puoi ottenere ciò utilizzando uno di questi 2 metodi:

  • utilizzando le funzioni func_num_args () e func_get_arg () ;
  • utilizzando argomenti NULL;

Come usare

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

Preferisco il secondo metodo perché è pulito e facile da capire, ma a volte potrebbe essere necessario il primo metodo.


1
Hai bisogno del doppio "=" qui o tutte le espressioni restituiranno true. Inoltre, le espressioni nel 2 ° esempio restituiranno sempre true perché una variabile è sempre uguale a se stessa.
chuckieDub

buon punto, ma funziona davvero. In PHP questo codice $x = null; if ($x) echo "true"; else echo "false";stamperà "false", anche se $ x var ha un valore ("null" in questo codice). Inoltre, in entrambi i metodi stiamo usando l'operatore ternario, quindi è corretto usare solo un "=". Se provi conmethod(); method(1); method(1, 2); , la prima chiamata assocerà arg1 e arg2 ai valori predefiniti, la seconda chiamata assocerà il secondo arg al valore predefinito e "1" al primo arg. L'ultima chiamata non assocerà i valori predefiniti.
Daniel Loureiro

1
function method_2 ($ arg1 = "default_value_fot_arg1", $ arg2 = "default_value_fot_arg2") {quindi php si occupa di cose relative ai parametri e puoi anche passare null come parametro (perché le persone usano null non lo so)
nerkn

1
@nerkn, hai ragione, PHP attualmente supporta gli argomenti predefiniti. Lol, ricordo quando dovevamo fare molte soluzioni alternative per ottenere cose semplici. Bei tempi: P Puoi ancora vedere questi approcci nei vecchi codici (pre-5.5), anche se.
Daniel Loureiro

4

Penso che tu possa usare gli oggetti anche come params-transport.

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

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

Ovviamente, devi impostare i valori predefiniti per "optParam8" e "optParam2" in questa funzione, in altri casi otterrai "Avviso: proprietà non definita: stdClass :: $ optParam2"

Se si utilizzano array come parametri di funzione, mi piace in questo modo impostare i valori predefiniti:

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 sono richiesti solo due valori per creare l'oggetto con uno stato valido, è possibile rimuovere semplicemente tutti gli altri argomenti opzionali e fornire i setter (a meno che non si desideri che vengano modificati in fase di esecuzione). Quindi basta istanziare l'oggetto con i due argomenti richiesti e impostare gli altri come necessario tramite il setter.

Ulteriore lettura


2

So che questo è un vecchio post, ma stavo avendo un problema come l'OP e questo è ciò che mi è venuto in mente.

Esempio di array che potresti passare. Puoi riordinarlo se è richiesto un ordine particolare, ma per questa domanda questo farà ciò che viene richiesto.

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

Questo è gestibile, facile da leggere e i punti di estrazione dei dati possono essere aggiunti e rimossi in un momento in qualsiasi punto della codifica ed evitare comunque una massiccia riscrittura. Ho usato i tasti interi per coincidere con la domanda originale dell'OP, ma i tasti stringa potevano essere usati altrettanto facilmente. Infatti per leggibilità lo consiglierei.

Inseriscilo in un file esterno per 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;
}

mettilo all'inizio se il file.

$argument_set = array(); 

Basta usarli per assegnare la numerazione / denominazione al pezzo successivo di dati in base alla provenienza dei dati.

$argument_set[1][] = $some_variable; 

E infine passa l'array

unknown_number_arguments($argument_set);

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

È possibile creare una funzione regolare e quindi aggiungere le variabili facoltative assegnando loro un valore Null predefinito.

Un Null è ancora un valore, se non chiami la funzione con un valore per quella variabile, non sarà vuoto, quindi nessun errore.


2
Puoi spiegare tutto questo ulteriormente? Il codice fornito non è sintatticamente valido, poiché i nomi delle variabili non possono iniziare con un numero
Nico Haase,

0

Se di solito passi solo l'ottavo valore, puoi riordinare i parametri in modo che sia il primo. Devi solo specificare i parametri fino all'ultimo che vuoi impostare.

Se stai usando valori diversi, hai 2 opzioni.

Uno potrebbe essere quello di creare un insieme di funzioni wrapper che accettano parametri diversi e impostano i valori predefiniti sugli altri. Questo è utile se usi solo poche combinazioni, ma può diventare molto disordinato rapidamente.

L'altra opzione è passare un array in cui le chiavi sono i nomi dei parametri. È quindi possibile verificare se nell'array è presente un valore con una chiave e, in caso contrario, utilizzare il valore predefinito. Ma ancora una volta, questo può diventare disordinato e aggiungere molto codice extra se hai molti parametri.


0

PHP consente argomenti predefiniti ( collegamento ). Nel tuo caso, puoi definire tutti i parametri da 3 a 8 come NULL o come una stringa vuota "" a seconda del codice della funzione. In questo modo è possibile chiamare la funzione solo utilizzando i primi due parametri.

Per esempio:

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

Idea interessante ... tuttavia la tua proposta non risolve il problema. Infatti, se aggiungi informazioni su quale argomento viene ripetuto (ad esempio usando echo " this is arg3: " . $arg3;, ecc., Vedrai che la chiamata ad esempio yourFunction(3, 2, $arg8=5);verrà stampata 32 this is arg3: 5. Il problema è che la posizione del parametro è ancora importante quando si passano parametri opzionali in PHP ... nomi di parametro non sono sufficienti per mappare i valori dei parametri ai nomi dei parametri
mastropi

0

Basta impostare Null per ignorare i parametri che non si desidera utilizzare e quindi impostare il parametro necessario in base alla posizione.

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.