it-swarm.com.de

Verwenden von Standardargumenten in einer Funktion

Ich bin verwirrt über Standardwerte für PHP - Funktionen. Angenommen, ich habe eine Funktion wie diese:

function foo($blah, $x = "some value", $y = "some other value") {
    // code here!
}

Was ist, wenn ich das Standardargument für $ x verwenden und ein anderes Argument für $ y festlegen möchte? 

Ich habe mit verschiedenen Wegen experimentiert und werde immer verwirrter. Zum Beispiel habe ich diese beiden probiert:

foo("blah", null, "test");
foo("blah", "", "test");

Beide führen jedoch nicht zu einem korrekten Standardargument für $ x. Ich habe auch versucht, es mit dem Variablennamen zu setzen.

foo("blah", $x, $y = "test");   

Ich habe völlig erwartet, dass so etwas funktioniert. Aber es funktioniert überhaupt nicht wie erwartet. Es scheint, egal was ich tue, ich muss sowieso die Standardargumente eintippen, jedes Mal wenn ich die Funktion aufrufe. Und ich muss etwas offensichtliches vermissen. 

148
renosis

Ich würde vorschlagen, die Funktionsdeklaration wie folgt zu ändern, damit Sie tun können, was Sie möchten:

function foo($blah, $x = null, $y = null) {
    if (null === $x) {
        $x = "some value";
    }

    if (null === $y) {
        $y = "some other value";
    }

    code here!

}

Auf diese Weise können Sie einen Aufruf wie foo('blah', null, 'non-default y value'); ausführen und ihn nach Belieben arbeiten lassen, wobei der zweite Parameter $x noch seinen Standardwert erhält.

Wenn Sie bei dieser Methode einen Nullwert übergeben, möchten Sie den Standardwert für einen Parameter, wenn Sie den Standardwert für einen Parameter überschreiben möchten, der danach folgt.

Wie in anderen Antworten festgestellt, 

standardparameter funktionieren nur als letzte Argumente für die Funktion. Wenn Sie die Standardwerte in der Funktionsdefinition deklarieren möchten, Es gibt keine Möglichkeit, einen Parameter wegzulassen und einen folgenden Parameter zu überschreiben.

Wenn ich eine Methode habe, die eine unterschiedliche Anzahl von Parametern und Parameter verschiedener Typen akzeptieren kann, erkläre ich oft die Funktion ähnlich der von Ryan P. gezeigten Antwort.

Hier ist ein anderes Beispiel (dies beantwortet Ihre Frage nicht, ist aber hoffentlich informativ:

public function __construct($params = null)
{
    if ($params instanceof SOMETHING) {
        // single parameter, of object type SOMETHING
    } else if (is_string($params)) {
        // single argument given as string
    } else if (is_array($params)) {
        // params could be an array of properties like array('x' => 'x1', 'y' => 'y1')
    } else if (func_num_args() == 3) {
        $args = func_get_args();

        // 3 parameters passed
    } else if (func_num_args() == 5) {
        $args = func_get_args();
        // 5 parameters passed
    } else {
        throw new InvalidArgumentException("Could not figure out parameters!");
    }
}
144
drew010

Optionale Argumente funktionieren nur am Ende eines Funktionsaufrufs. Es gibt keine Möglichkeit, einen Wert für $ y in Ihrer Funktion anzugeben, ohne auch $ x anzugeben. Einige Sprachen unterstützen dies über benannte Parameter (z. B. VB/C #), jedoch nicht PHP.

Sie können dies emulieren, wenn Sie anstelle von Argumenten ein assoziatives Array für Parameter verwenden, d.

function foo(array $args = array()) {
    $x = !isset($args['x']) ? 'default x value' : $args['x'];
    $y = !isset($args['y']) ? 'default y value' : $args['y'];

    ...
}

Dann rufen Sie die Funktion wie folgt auf:

foo(array('y' => 'my value'));
35
Ryan P

Es ist tatsächlich möglich:

foo( 'blah', (new ReflectionFunction('foo'))->getParameters()[1]->getDefaultValue(), 'test');

Ob du das möchtest, ist eine andere Geschichte :)


AKTUALISIEREN:

Die Gründe, um diese Lösung zu vermeiden, sind:

  • es ist (wohl) hässlich
  • es hat einen offensichtlichen Aufwand. 
  • wie die anderen Antworten belegen, gibt es Alternativen

In Situationen, in denen:

  • sie wollen/können die ursprüngliche Funktion nicht ändern.
  • sie könnten die Funktion aber ändern:

    • null (oder gleichwertig) ist keine Option (siehe DiegoDDs comment )
    • sie möchten weder mit einem Associative noch mit func_num_args() gehen
    • ihr Leben hängt davon ab, ein paar LOCs zu retten

Was die Leistung angeht, zeigt ein sehr einfacher Test , dass der Funktionsaufruf 25 mal langsamer durch die Verwendung der Reflection-API zum Abrufen der Standardparameter bewirkt wird, während weniger als eine Mikrosekunde dauert. Sie sollten wissen, ob Sie damit leben können.

Wenn Sie es in einer Schleife verwenden möchten, sollten Sie natürlich den Standardwert erhalten.

18
David
function image(array $img)
{
    $defaults = array(
        'src'    => 'cow.png',
        'alt'    => 'milk factory',
        'height' => 100,
        'width'  => 50
    );

    $img = array_merge($defaults, $img);
    /* ... */
}
10
zloctb

Die einzige Möglichkeit, dies zu tun, besteht darin, den Parameter wegzulassen. Der einzige Weg, den Parameter auszulassen, besteht darin, die Parameterliste so anzuordnen, dass diejenige, die Sie auslassen möchten, nach den Parametern liegt, die Sie HABEN festlegen. Zum Beispiel:

function foo($blah, $y = "some other value", $x = "some value")

Dann kannst du foo anrufen:

foo("blah", "test");

Dies führt zu:

$blah = "blah";
$y = "test";
$x = "some value";
3
Wes Crow

Ich hatte kürzlich dieses Problem und fand diese Frage und Antworten. Während die obigen Fragen funktionieren, besteht das Problem darin, dass sie den IDEs, die sie unterstützen (wie PHPStorm), die Standardwerte nicht anzeigen.

 enter image description here

wenn Sie null verwenden, wissen Sie nicht, wie der Wert lautet, wenn Sie ihn leer lassen.

Die Lösung, die ich bevorzuge, ist, den Standardwert in die Funktionsdefinition mit aufzunehmen:

protected function baseItemQuery(BoolQuery $boolQuery, $limit=1000, $sort = [], $offset = 0, $remove_dead=true)
{
    if ($limit===null) $limit =1000;
    if ($sort===null) $sort = [];
    if ($offset===null) $offset = 0;
    ...

Der einzige Unterschied ist, dass ich sicherstellen muss, dass sie gleich sind - aber ich denke, das ist ein kleiner Preis, der für die zusätzliche Klarheit zu zahlen ist.

2
Yehosef

Das kann man nicht direkt machen, aber ein bisschen Code-Fummeln macht es möglich, zu emulieren.

function foo($blah, $x = false, $y = false) {
  if (!$x) $x = "some value";
  if (!$y) $y = "some other value";

  // code
}
2
kba

Übergeben Sie statt einzelner Parameter ein Array an die Funktion und verwenden Sie den Nullkoaleszenzoperator (PHP 7+).

Unten führe ich ein Array mit 2 Elementen durch. Innerhalb der Funktion prüfe ich, ob der Wert für item1 festgelegt ist, wenn kein Standard-Tresor zugewiesen ist.

$args = ['item2' => 'item2',
        'item3' => 'value3'];

    function function_name ($args) {
        isset($args['item1']) ? $args['item1'] : 'default value';
    }
0
Roger
<?php
function info($name="George",$age=18) {
echo "$name is $age years old.<br>";
}
info();     // prints default values(number of values = 2)
info("Nick");   // changes first default argument from George to Nick
info("Mark",17);    // changes both default arguments' values

?>
0
Odin

Dies ist der Fall, wenn Objekte besser sind - weil Sie Ihr Objekt so einrichten können, dass es x und y enthält, Standardwerte festlegen usw. 

Der Ansatz mit dem Array ist in der Nähe, um ein Objekt zu erstellen (Tatsächlich ist das Objekt eine Reihe von Parametern und Funktionen, die über das Objekt funktionieren, und die Funktion, die das Array verwendet, funktioniert mit einigen Bündel-Ov-Parametern.)

Natürlich können Sie immer ein paar Tricks machen, um null oder ähnliches als Standard festzulegen

0
SergeS

Sie können auch überprüfen, ob Sie eine leere Zeichenfolge als Argument haben, sodass Sie Folgendes aufrufen können:

foo('blah', "", 'non-default y value', null);

Unterhalb der Funktion:

function foo($blah, $x = null, $y = null, $z = null) {
    if (null === $x || "" === $x) {
        $x = "some value";
    }

    if (null === $y || "" === $y) {
        $y = "some other value";
    }

    if (null === $z || "" === $z) {
        $z = "some other value";
    }

    code here!

}

Es spielt keine Rolle, ob Sie null oder "" erhalten Sie immer noch das gleiche Ergebnis.

0
Mustafa Ekici