7

How can I implement the named argument feature in PHP 7+?

The ideal syntax is:

find($wildcard, relative = true, listIfEmpty = false) {
    ...
}

But there is no such solution. In the answer, I implemented the shortest possible solution that supports:

  • Refactoring
  • Type Hints for the params and function result
  • Reusable param set
  • Typesafe params
  • Default values for params
  • Getter for each param ( no hard-coded string )
  • Very simple setter/getter that you only change one name for each param

See the answer for more information and implementation

Hamed Azimi
  • 145
  • 10
Behnam
  • 2,212
  • 2
  • 22
  • 32
  • Possible duplicate of [Named function parameters in PHP](https://stackoverflow.com/questions/19126860/named-function-parameters-in-php) – miken32 Aug 20 '19 at 23:28
  • @miken32 Do you see that is a Question/Answer by me?! – Behnam Aug 22 '19 at 02:49
  • Yes. The question is a duplicate and should be removed. The answer should be posted as an answer to the other question. – miken32 Aug 22 '19 at 04:13
  • 2
    That is very bad manner that instead of voting up for complete answer and technical information that presents, you are sticking to details about managing questions. – Behnam Aug 22 '19 at 22:42
  • For PHP8+ exists in-built solution: https://stackoverflow.com/a/64072408/7082164 – Jsowa Sep 25 '20 at 23:24
  • What **exactly** are you looking for? The given code does not look like valid code that would compile using PHP 7 – Nico Haase Feb 19 '21 at 21:17
  • The earliest asked question on the topic of "named parameters" was in 2009 and contains [a comprehensive/generous answer posted 2020-11-25 (the day before the new feature was deployed with PHP8.0)](https://stackoverflow.com/a/64997399/2943403). I consider this page to be the "canonical" on Stack Overflow. – mickmackusa Aug 22 '23 at 22:05

2 Answers2

4

First, do it once in your Framework, or globally:

// the superclass that every params class will extend this
class params {
  protected function setter($key, $value) {
    if ($value === null) {
      return $this->{$key};
    }

    $this->{$key} = $value;
    return $this;
  }
}

Then, do this for each function that requires named arguments with proper names:

// define a helper method for simple instantiation
function params_find() { return new params_find(); }

// a params class that will use from find() method
class params_find extends params {

  // list of params with default values
  // below list is just a sample
  protected $listIfEmpty   = false;
  protected $structured    = true;
  protected $relative      = false;
  protected $prefix        = "";
  protected $justFileNames = false;

  // for each param duplicate line and just change function name exactly matching param name. setter/getter will done automatically
  function listIfEmpty($val = null)   { return $this->setter(__FUNCTION__, $val); }
  function structured($val = null)    { return $this->setter(__FUNCTION__, $val); }
  function relative($val = null)      { return $this->setter(__FUNCTION__, $val); }
  function prefix($val = null)        { return $this->setter(__FUNCTION__, $val); }
  function justFileNames($val = null) { return $this->setter(__FUNCTION__, $val); }
}

After that, write your function using this feature:

// your function that uses named arguments
// in this example $wildcard argument is required
function find($wildcard = [], params_find $opt = null) {
  if ($opt === null) {
    $opt = params_find();
  }

  // do something with your params like this
  if ($opt->structured()) {
    // ...
  }

  return $something_if_you_want;
}

Finally, use it with the simplest interface:

// finally use your function with some params ( other params will have default values )
$files = find("*.css", params_find()
  ->structured(false)
  ->listIfEmpty(true)
  ->prefix("something")
);


// if you need all default values
$files = find("*.css");


// reusable options
$opt = params_find()
  ->listIfEmpty(false)
  ->prefix("something")
)
$files1 = find("*.css", $opt);
$files2 = find("*.html", $opt);
$files3 = find("*.scss", $opt
  ->structured(true)
);
Hamed Azimi
  • 145
  • 10
Behnam
  • 2,212
  • 2
  • 22
  • 32
  • Please share more details - where do you use named parameters in the given code? `params_find() ->structured(false)` looks like something completely different – Nico Haase Feb 19 '21 at 21:18
2

It's a PHP 8 >= feature now: https://wiki.php.net/rfc/named_params

<?php
// Using positional arguments:
array_fill(0, 100, 50);
 
// Using named arguments:
array_fill(start_index: 0, num: 100, value: 50);
celsowm
  • 846
  • 9
  • 34
  • 59