phpphp-5.5named-parametershacklangphp-7

PHP: Sending a list of options as an argument (alternative to named parameters/ argument bag)


I wish to give a list of options as an argument to a function.

The Ideal Scenario: Named Parameters

If PHP has named parameters it would be done like so:

function setOptions($title, $url, $public = true, $placeholder = "type here...") {
   ...
}

setOptions($title = "Hello World", $url = "example.com", $placeholder = "hi"); 

Unfortunately PHP does not have named parameters (please tell me if PHP7 is planned to have some as a comment).

The solution everyone else is using: Associative Array

Most PHP scripts I have seen use an alternative array approach like so:

function setOptions($options) {
   ...
}

setOptions(array(
   'title' => "Hello World",
   'url' => "example.com",
   'placeholder' => "hi"
));

Drawbacks of Associative Array Approach

Although this works fine, there are the following drawbacks:

Is there a better way?

Is there a better way that can address these issues (either in current PHP or PHP7 or maybe even hacklang(?)).


Solution

  • In Hack, you can use Shapes. Shapes define a structure for associative arrays so that things can be autocompleted (depending on IDE support) and spelling mistakes are picked up by the type checker.

    For instance, your example could be reworked like:

    function setOptions(shape(
      'title' => string,
      'url' => string,
      'public' => ?bool,
      'placeholder' => ?string,
    ) $options) {
      $title = $options['title'];
      $url = $options['url'];
      $public = Shapes::idx($options, 'public', true);
      $placeholder = Shapes::idx($options, 'placeholder', 'type here...');
      ...
    }
    
    setOptions(shape(
      'title' => 'Hello World',
      'url' => 'example.com',
      'placeholder' => 'hi',
    ));
    

    This marks title and url to both be required options and public and placeholder are optional (all nullable types in shapes are considered to be optional). Shapes::idx is then used to get the value provided, or the default value (the third argument) if a value was not passed in.