wake-up-neo.com

Wie würde ich optionale Argumente in einem Funktionsaufruf überspringen?

OK, ich habe total vergessen, wie man Argumente in PHP überspringt.

Sagen wir, ich habe:

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

Wie rufe ich diese Funktion auf, damit der mittlere Parameter den Standardwert annimmt (dh '50')?

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

Wäre das obige richtig? Ich kann nicht scheinen, dass dies funktioniert.

77
Sebastian

Dein Beitrag ist richtig.

Wenn Sie am Ende der Parameterliste einen optionalen Parameter verwenden müssen, müssen Sie leider alles bis zu diesem letzten Parameter angeben. Wenn Sie mischen und zusammenpassen möchten, geben Sie ihnen normalerweise die Standardwerte '' oder null und verwenden sie nicht innerhalb der Funktion, wenn es sich um diesen Standardwert handelt.

47
zombat

Es gibt keine Möglichkeit, ein Argument "zu überspringen", als einen Standardwert wie false oder null anzugeben. 

Da es an PHP an syntaktischem Zucker mangelt, werden Sie häufig Folgendes sehen:

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

Was in den Kommentaren beredt gesagt wird, verwendet Arrays, um benannte Argumente zu emulieren.

Dies gibt ultimative Flexibilität, kann jedoch in einigen Fällen nicht erforderlich sein. Zumindest können Sie alles, was Sie für gewöhnlich nicht erwarten, bis zum Ende der Argumentationsliste verschieben.

36

Nein, es ist nicht möglich, Argumente auf diese Weise zu überspringen. Sie können die übergebenen Argumente only auslassen, wenn sie sich am Ende der Parameterliste befinden.

Dafür gab es einen offiziellen Vorschlag: https://wiki.php.net/rfc/skipparams , der abgelehnt wurde. Die Seite mit den Vorschlägen enthält Links zu anderen SO - Fragen zu diesem Thema.

31
Cristik

In Bezug auf die Möglichkeit, optionale Argumente zu überspringen, hat sich nichts geändert, jedoch für die korrekte Syntax und für die Angabe von NULL für Argumente, die ich überspringen möchte.

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

Dies kann so aufgerufen werden: getData('some name',NULL,'23'); und jeder, der die Funktion in der Zukunft aufruft, muss sich nicht jedes Mal an die Standardwerte oder die für sie deklarierte Konstante erinnern. 

5
Ibrahim Lawal

Die einfache Antwort lautet Nein . Aber warum überspringen, wenn Neuanordnung der Argumente dies erreicht?

Ihre ist eine " falsche Verwendung von Standardfunktionsargumenten " und wird nicht so funktionieren, wie Sie es erwarten.

Eine Randnotiz aus der PHP Dokumentation:

Wenn Sie Standardargumente verwenden, sollten sich alle Standardargumente auf der rechten Seite aller nicht standardmäßigen Argumente befinden. Andernfalls funktionieren die Dinge nicht wie erwartet.

Folgendes berücksichtigen:

function getData($name, $limit = '50', $page = '1') {
    return "Select * FROM books WHERE name = $name AND page = $page limit $limit";
}

echo getData('some name', '', '23');   // won't work as expected

Die Ausgabe wird sein:

"Select * FROM books WHERE name = some name AND page = 23 limit"

Die korrekte Verwendung der Standardfunktionsargumente sollte folgendermaßen aussehen:

function getData($name, $page = '1', $limit = '50') {
    return "Select * FROM books WHERE name = $name AND page = $page limit $limit";
}

echo getData('some name', '23');  // works as expected

Die Ausgabe wird sein:

"Select * FROM books WHERE name = some name AND page = 23 limit 50"

Wenn Sie den Standardwert nach dem Standardwert rechts setzen, stellen Sie sicher, dass der Standardwert für diese Variable immer geändert wird, wenn er nicht definiert/angegeben ist. Hier ist ein Link als Referenz und woher diese Beispiele stammen.

Bearbeiten: Setzen Sie es auf null, wie von anderen vorgeschlagen, und stellen Sie eine weitere Alternative dar, die jedoch möglicherweise nicht Ihren Wünschen entspricht. Der Standardwert wird immer auf null gesetzt, wenn er nicht definiert ist.

4
Nelson Owalo

Sie können keine Argumente überspringen, aber Sie können Array-Parameter verwenden und Sie müssen nur einen Parameter definieren, der ein Array von Parametern ist.

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

Sie können beliebig viele Parameter hinzufügen, die Sie nicht definieren müssen. Wenn Sie die Funktion aufrufen, geben Sie Ihre Parameter folgendermaßen ein:

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

Wenn Sie einen Parameter überspringen möchten (müssen Sie), verwenden Sie den Standardparameter, um auf der sicheren Seite zu sein.

(Die Einstellung auf null, wenn der Standardparameter '' oder ähnlich oder umgekehrt ist, bringt Sie in Schwierigkeiten ...)

2
Frank Nocke

Wie oben erwähnt, können Sie keine Parameter überspringen. Ich habe diese Antwort geschrieben, um einen Nachtrag zu liefern, der zu groß war, um ihn in einen Kommentar einzufügen.

@Frank Nocke schlägt vor , um die Funktion mit ihren Default-Parametern aufzurufen, also zum Beispiel mit

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

du solltest benutzen

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

dies ist funktional gleichbedeutend mit dem Weglassen der ersten beiden Parameter ($b und $c).

Es ist nicht klar, welche Standardeinstellungen verwendet werden (ist 0 als Standardwert angegeben, oder ist es wichtig?).

Es besteht auch die Gefahr, dass das Problem der Standardwerte mit einer externen (oder integrierten) Funktion verbunden ist, wenn die Standardwerte durch den Funktionsautor (oder den Methodenautor) geändert werden könnten. Wenn Sie also Ihren Aufruf im Programm nicht ändern, können Sie unbeabsichtigt sein Verhalten ändern.

Eine Problemumgehung könnte darin bestehen, einige globale Konstanten zu definieren, z. B. DEFAULT_A_B, bei dem es sich um den "Standardwert des Parameters B der Funktion A" und um "Parameter" folgendermaßen handelt:

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

Für Klassen ist es einfacher und eleganter, wenn Sie Klassenkonstanten definieren, da sie Teil des globalen Gültigkeitsbereichs sind, z.

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.

Beachten Sie, dass diese Standardkonstante im Code genau einmal definiert ist (selbst in der Methodendeklaration gibt es keinen Wert). Bei unerwarteten Änderungen geben Sie die Funktion/Methode daher immer mit dem korrekten Standardwert an.

Die Klarheit dieser Lösung ist natürlich besser als die Angabe von unformatierten Standardwerten (wie NULL, 0 usw.), die dem Leser nichts mitteilen.

(Ich bin damit einverstanden, dass ein Aufruf wie $var = a(,,'ddd'); die beste Option ist)

2
Voitcus

Wie bereits angedeutet , nichts hat sich geändert . Vorsicht, zu viele Parameter (insbesondere optionale) sind ein starker Indikator für Codegeruch.

Vielleicht macht Ihre Funktion zu viel:

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

Einige Parameter können logisch gruppiert werden:

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

In letzter Instanz können Sie immer ein Ad-hoc Parameter-Objekt einführen:

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

(Dies ist nur eine verklärte Version der weniger formalen parameter array - Technik )

Manchmal ist der Grund, warum ein Parameter optional ist, falsch. Ist $page in diesem Beispiel wirklich optional? Hat das Speichern einiger Charaktere wirklich einen Unterschied?

// 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

Setzen Sie das Limit auf null

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

und rufen Sie diese Funktion auf

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

wenn Sie das Limit festlegen möchten, können Sie es als Argument übergeben

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

Dieser Ausschnitt:

 Funktion getData ($ name, $ options) {
 $ default = array (
 'limit' => 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)); 

Antwort ist :

 Array 
 (
 [limit] => 50 
 [page] => 2 
) 
 Array 
 (
 [Limit] => 2 
 [Seite] => 2 
) 
 Array 
 (
 [limit] => 10 
 [page] => 10 
) 

0
nobody0day

Dies ist eine Art alte Frage mit einer Reihe technisch kompetenter Antworten, aber es ruft nach einem der modernen Entwurfsmuster in PHP: der objektorientierten Programmierung. Anstatt eine Sammlung primärer skalarer Datentypen einzuspeisen, sollten Sie ein "injiziertes Objekt" verwenden, das alle Daten enthält, die von der Funktion . http://php.net/manual/de/language.types benötigt werden .intro.php

Das injizierte Objekt verfügt möglicherweise über Eigenschaftsprüfungsroutinen usw. Wenn die Instantiierung und das Einfügen von Daten in das injizierte Objekt nicht die gesamte Validierung bestehen kann, kann der Code sofort eine Ausnahme auslösen und die Anwendung kann den umständlichen Prozess des Umgangs vermeiden mit möglicherweise unvollständigen Daten.

Wir können das injizierte Objekt mit einem Tipp versehen, um Fehler vor der Bereitstellung zu erkennen. Einige Ideen sind in diesem Artikel von vor einigen Jahren zusammengefasst.

https://www.experts-exchange.com/articles/18409/Nutzen-benannt-Parameter-in-PHP-Funktions-Rufe.html

0
Ray Paseur

Das würde ich tun:

<?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 */

?>

Hoffe das hilft jemandem

0

Wie alle anderen bereits sagten, ist das, was Sie wollen, in PHP nicht möglich, ohne dass Codezeilen in die Funktion eingefügt werden.

Sie können diesen Code jedoch an die Spitze einer Funktion setzen, um Ihre Funktionalität zu erhalten:

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

Grundsätzlich erhalte ich mit debug_backtrace() den Funktionsnamen, in den dieser Code eingefügt wird, um dann ein neues ReflectionFunctionNAME _ -Objekt und eine Schleife zu erstellen alle Funktionsargumente.

In der Schleife überprüfe ich einfach, ob das Funktionsargument empty() UND das Argument "optional" ist (bedeutet, es hat einen Standardwert). Wenn ja, weise ich dem Argument einfach den Standardwert zu.

Demo

0
Rizier123