Funkcja PHP z opcjonalnymi parametrami

107

Napisałem funkcję PHP, która akceptuje 10 parametrów, ale wymagane są tylko 2. Czasami chcę zdefiniować ósmy parametr, ale nie chcę wpisywać pustych ciągów dla każdego z parametrów, dopóki nie osiągnę ósmego.

Pomysł, jaki miałem, to przekazanie abstrakcyjnej funkcji z tablicą parametrów, która przekazuje ją do funkcji rzeczywistej.

Czy istnieje lepszy sposób na skonfigurowanie funkcji, aby móc przekazywać tylko te parametry, które chcę?

user481826
źródło
To jest dziwne. Wbudowane funkcje w php mogą mieć opcjonalne parametry. Dlaczego więc nie możemy budować takich funkcji?
Rodrigo
2
Zauważ, że wiele z tych odpowiedzi jest PRZERWANY ... PHP obsługuje teraz funkcje z listami argumentów o zmiennej długości .
ashleedawg

Odpowiedzi:

62

Niech funkcja przyjmuje jeden parametr: tablicę. Przekaż rzeczywiste parametry jako wartości w tablicy.


Edycja: link w komentarzu Pekki prawie to podsumowuje.

Matt Ball
źródło
1
To jest dziwne. Wbudowane funkcje w php mogą mieć opcjonalne parametry. Dlaczego więc nie możemy budować takich funkcji?
Rodrigo
1
@Rodrigo zdefiniowanie takich funkcji jest absolutnie wykonalne. Są one jednak pozycyjne opcjonalne, co jest dość kiepskie dla wszystkiego poza jednym opcjonalnym parametrem.
Matt Ball
1
Ok, próbowałem z [], teraz widzę jak to zrobić tutaj: stackoverflow.com/a/34869/1086511
Rodrigo
Można zrobić więcej niż tylko sugestia „użyj tablicy” - spójrz na odpowiedź Walfa na podobne pytanie i bardziej szczegółowy przykład w tym samym wątku
DJDave
63

W tym przypadku przekazałem tablicę, w której kluczem jest nazwa parametru, a wartością jest wartość.

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

function func($required, $requiredTwo, $optional) {
  if(isset($optional["param2"])) {
    doWork();
  }
}
Rabbott
źródło
Na przykład, czy $ opcjonalne nie powinno być ustawione jako globalne w funkcji?
user481826
1
światowy? Nie..? Tworzysz tę tablicę przed wywołaniem funkcji i przekazujesz ją. Mój kod jest przykładem opisu tego, co należy zrobić, autorstwa Matta Ballsa.
Rabbott
Można zrobić więcej niż tylko sugestie „użyj tablicy” - spójrz na odpowiedź Walfa na podobne pytanie i bardziej szczegółowy przykład w tym samym wątku
DJDave
45

Aby osiągnąć to, co chcesz, użyj tablicy Jak powiedział Rabbot (chociaż może to stać się uciążliwe do dokumentowania / utrzymywania, jeśli jest używane nadmiernie). Lub po prostu użyj tradycyjnych opcjonalnych argumentów.

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

Jednak zwykle stwierdzam, że kiedy zaczynam pisać funkcję / metodę z tak wieloma argumentami - najczęściej jest to zapach kodu i można go ponownie przekształcić / wyabstrahować w coś znacznie czystszego.

//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
źródło
W 2010 roku pojęcia takie jak „zapach kodu”, „refaktoryzacja” czy „konserwacja kodu” nie były popularne w naszej społeczności. Miałeś krok przed większością z nas :)
Billal Begueradj
15

W PHP 5.6 i późniejszych, listy argumentów mogą zawierać token ... oznaczający, że funkcja przyjmuje zmienną liczbę argumentów. Argumenty zostaną przekazane do podanej zmiennej jako tablica; na przykład:

Przykład Użycie ... do uzyskania dostępu do zmiennych argumentów

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

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

Powyższy przykład wyświetli:

10

Lista argumentów o zmiennej długości Dokumentacja PHP

Mentos1386
źródło
Ta odpowiedź zasługuje na więcej punktów. Nie nadaje się do mojego konkretnego przypadku, ale zawiera dobre informacje i jest łatwy do zrozumienia. PHP 7.3 już wkrótce! 5.6 i 7 to EOL.
AdheneManx,
12

Możesz po prostu ustawić wartość domyślną na null.

<?php
function functionName($value, $value2 = null) {
// do stuff
}
Blake Stevenson
źródło
2
Najlepsza odpowiedź, ale zamień nullją na nie-bity typu daty. na przykład array()dla tablic
Mohamed hesham
Dziękuję ... Właśnie tego szukałem
Davide De Maestri
12

UWAGA: To jest stara odpowiedź, dla PHP 5.5 i starszych . PHP 5.6+ obsługuje domyślne argumenty

W PHP 5.5 i starszych możesz to osiągnąć za pomocą jednej z następujących 2 metod:

  • używając funkcji func_num_args () i func_get_arg () ;
  • używając argumentów NULL;

Jak używać

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

Wolę drugą metodę, ponieważ jest przejrzysta i łatwa do zrozumienia, ale czasami możesz potrzebować pierwszej metody.

Daniel Loureiro
źródło
1
Potrzebujesz podwójnego „=” tutaj lub wszystkie wyrażenia zwrócą prawdę. Ponadto wyrażenia z drugiego przykładu zawsze będą zwracać prawdę, ponieważ zmienna jest zawsze sobie równa.
chuckieDub
słuszna uwaga, ale to faktycznie działa. W PHP ten kod $x = null; if ($x) echo "true"; else echo "false";wypisze „false”, nawet jeśli zmienna $ x ma wartość („null” w tym kodzie). Ponadto w obu metodach używamy operatora trójskładnikowego, więc poprawne jest użycie tylko jednego „=”. Jeśli wykonasz test z method(); method(1); method(1, 2);, to pierwsze wywołanie skojarzy arg1 i arg2 z wartościami domyślnymi, drugie wywołanie skojarzy drugi argument z wartością domyślną i „1” dla pierwszego argumentu. Ostatnie wywołanie nie skojarzy wartości domyślnych.
Daniel Loureiro
1
function method_2 ($ arg1 = "default_value_fot_arg1", $ arg2 = "default_value_fot_arg2") {więc php zajmuje się parametrami, a także możesz
podać
1
@nerkn, masz rację, PHP obecnie obsługuje domyślne argumenty. Lol, pamiętam, kiedy musieliśmy wykonać wiele obejść, aby osiągnąć proste rzeczy. Dobre czasy: P Nadal możesz zobaczyć te podejścia w starych kodach (przed 5.5), chociaż.
Daniel Loureiro
4

Myślę, że możesz też używać obiektów jako nośników parametrów.

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

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

Oczywiście musisz ustawić domyślne wartości dla "optParam8" i "optParam2" w tej funkcji, w innym przypadku otrzymasz "Uwaga: Undefined property: stdClass :: $ optParam2"

Jeśli używasz tablic jako parametrów funkcji, podoba mi się ten sposób ustawiania wartości domyślnych:

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
źródło
2

Jeśli do utworzenia obiektu z prawidłowym stanem wymagane są tylko dwie wartości, możesz po prostu usunąć wszystkie inne opcjonalne argumenty i podać je ustawiające (chyba że nie chcesz, aby były zmieniane w czasie wykonywania). Następnie po prostu utwórz instancję obiektu z dwoma wymaganymi argumentami i ustaw pozostałe zgodnie z potrzebami za pomocą metody ustawiającej.

Dalsza lektura

Gordon
źródło
2

Wiem, że to stary post, ale miałem problem jak OP i to właśnie wymyśliłem.

Przykład tablicy, którą możesz przekazać. Możesz zamówić to ponownie, jeśli było wymagane określone zamówienie, ale w przypadku tego pytania zrobi to, o co zostało zadane.

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

Jest to łatwe w zarządzaniu, łatwe do odczytania, a punkty wyodrębniania danych można dodawać i usuwać w dowolnym momencie w dowolnym miejscu kodowania, a jednocześnie uniknąć masowego przepisywania. Użyłem kluczy całkowitych, aby dopasować się do oryginalnego pytania OP, ale klucze łańcuchowe mogą być równie łatwo używane. Właściwie dla czytelności radziłbym to.

Dla ułatwienia umieść to w zewnętrznym pliku

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

umieść to na początku, jeśli plik.

$argument_set = array(); 

Po prostu użyj ich, aby przypisać kolejną część danych numerację / nazewnictwo w zależności od tego, skąd pochodzą dane.

$argument_set[1][] = $some_variable; 

I na koniec przekaż tablicę

unknown_number_arguments($argument_set);
Chris
źródło
1
function yourFunction($var1, $var2, $optional = Null){
   ... code
}

Możesz utworzyć zwykłą funkcję, a następnie dodać opcjonalne zmienne, nadając im domyślną wartość Null.

Wartość Null nadal jest wartością, jeśli nie wywołasz funkcji z wartością dla tej zmiennej, nie będzie ona pusta, więc nie ma błędu.

antoine serry
źródło
2
Czy możesz to wszystko dalej wyjaśnić? Podany kod jest niepoprawny pod względem składniowym, ponieważ nazwy zmiennych nie mogą zaczynać się od liczby
Nico Haase
0

Jeśli zwykle przekazujesz tylko ósmą wartość, możesz zmienić kolejność parametrów, tak aby była pierwsza. Musisz tylko określić parametry aż do ostatniego, który chcesz ustawić.

Jeśli używasz różnych wartości, masz 2 opcje.

Jednym z nich byłoby utworzenie zestawu funkcji opakowujących, które przyjmują różne parametry i ustawiają wartości domyślne dla innych. Jest to przydatne, jeśli używasz tylko kilku kombinacji, ale może szybko się skomplikować.

Inną opcją jest przekazanie tablicy, w której klucze są nazwami parametrów. Możesz wtedy po prostu sprawdzić, czy w tablicy jest wartość z kluczem, a jeśli nie, użyj wartości domyślnej. Ale znowu, może to stać się bałaganiarskie i dodać dużo dodatkowego kodu, jeśli masz dużo parametrów.

Alan Geleynse
źródło
0

PHP dopuszcza domyślne argumenty ( link ). W twoim przypadku możesz zdefiniować wszystkie parametry od 3 do 8 jako NULL lub jako pusty ciąg "" w zależności od kodu funkcji. W ten sposób możesz wywołać funkcję tylko przy użyciu pierwszych dwóch parametrów.

Na przykład:

<?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
źródło
Ciekawy pomysł ... jednak Twoja propozycja nie rozwiązuje problemu. W rzeczywistości, jeśli dodasz informacje o tym, który argument jest echo " this is arg3: " . $arg3;wywoływany (np . Przy użyciu , itp., Zobaczysz, że wywołanie np . yourFunction(3, 2, $arg8=5);Wydrukuje 32 this is arg3: 5. Problem w tym, że pozycja parametru nadal ma znaczenie przy przekazywaniu parametrów opcjonalnych w PHP ... nazwy parametrów nie wystarczą do odwzorowania wartości parametrów na nazwy parametrów
mastropi
0

Po prostu ustaw Null, aby ignorować parametry, których nie chcesz używać, a następnie ustaw wymagany parametr zgodnie z pozycją.

 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
źródło
-4
func( "1", "2", default, default, default, default, default, "eight" );
Flinsch
źródło
1
To nie jest poprawne PHP. defaultto słowo kluczowe w PHP .
Pang