Is it bad practice to define class parameters through an array?

When we look at Javascript frameworks such as Dojo, Mootools, jQuery, JS Prototype, etc., we see that parameters are often defined using such an array:

dosomething('mainsetting',{duration:3,allowothers:true,astring:'hello'}); 

Is it wrong to use this idea when writing a PHP class?

Example:

 class Hello { private $message = ''; private $person = ''; public function __construct($options) { if(isset($options['message'])) $this->message = $message; if(isset($options['person'])) $this->person = $person; } public function talk() { echo $this->person . ' says: ' . $this->message; } } 

Regular approach:

 class Hello { private $message = ''; private $person = ''; public function __construct() {} public function setmessage($message) { $this->message = $message; } public function setperson($person) { $this->person = $person; } public function talk() { echo $this->person . ' says: ' . $this->message; } } 

The advantage in the first example is that you can pass as many parameters as you want, and the class will retrieve only those that it needs.

For example, this may be convenient when extracting parameters from a JSON file:

 $options = json_decode($options); $hello = new Hello($options); 

Here is how I do it:

 $options = json_decode($options); $hello = new Hello(); if(isset($options['message'])) $hello->setmessage($options['message']); if(isset($options['person'])) $hello->setperson($options['person']); 

Is there a name for this template, and do you think this is bad practice?

I left validation, etc. in the examples to make it simple.

+4
source share
7 answers

There are good and bad aspects.

Good:

  • No need for multiple method signatures (i.e. when overloaded, if supported)
  • According to the previous point: methods can be called with arguments in any order
  • Arguments can be dynamically generated without having to specify each one that will be present (for example: you dynamically create an array of arguments based on user input and pass it to a function)
  • No need to use "template" methods like setName , setThis , setThat , etc., although you can still enable them
  • Default values ​​can be specified in the function tag rather than the signature (jQuery often uses this template, often $.extend parameters passed to the method with an array of default values. In your case, you will use array_merge() )

Bad:

  • If you do not properly advertise each option, your class may be more difficult to use because few will know which options are supported.
  • This is another step to create an array of arguments when you know in advance what you will need to pass
  • It is not always obvious to the user that default values ​​exist if documentation is not provided or if they have access to the source code.

In my opinion, this is an excellent technique. My favorite aspect is that you do not need to provide overloaded methods with different signatures and that the signature is not set in stone.

+12
source

There is nothing wrong with this approach, especially if you have a lot of parameters that you need to pass to the constructor. It also allows you to set default values ​​for them and array_merge() them inside the constructor (sort of like all jQuery plugins)

 protected $default_params = array( 'option1' => 'default_value' ); public function __construct($params = array()) { $this->params = array_merge($this->default_params, $params); } 

If you need live examples of this "template", check out the symfony structure, they use it almost everywhere: here is an example of the sfValidatorBase constructor

+3
source

When you specify argument names, they are called Named Notations vs Positional Notation, where the arguments must be in a specific order.

In PHP, you can pass the "options" parameter to give the same effect as other languages ​​(like Python), where you can use a genuine Named Notation. This is not a bad practice, but it is often done where there is a reason for this (i.e., in your example or in the case where there are many arguments, and they do not need to be set in any particular order).

+3
source

I don’t know the name, but I really doubt that this is bad practice, since you usually use this when you do not want to declare a small o fast function or class property

+1
source

If there are required parameters, they should be in the list of constructor parameters. Then you add additional parameters with default values.

 public function __construc($mandatory1, $mandatory2, $optional1="value", $optional2="value") { } 

If all your parameters are optional, then it may be useful to create a constructor that accepts an array. It would be easier to create an object than with a "normal constructor": you could provide only the necessary parameters, while with a "normal constructor", if you want to provide $ optional2, you must provide $ optional1 (even setting it to a value of default).

+1
source

I would not say my bad practice, at least if you trust a data source.

Another possibility is to dynamically call setters in accordance with the key of an array of parameters, for example:

 public function __construct($options) { foreach($options as $option => $value) { $method = 'set'.$option; if(method_exists($this, $method) call_user_func(array($this, $method, $value); } } 
+1
source

Why not get along? Ask for your piece of constructor and eat it with a static constructor named factory ":
$newHello = Hello::createFromArray($options);

First you have your own constructor with parameters. Then add a static method like this to one class:

 public static function createFromArray($options){ $a = isset($options['a']) ? $options['a'] : NULL; $b = isset($options['b']) ? $options['b'] : NULL; $c = isset($options['c']) ? $options['c'] : NULL; return new Hello($a, $b, $c); } 

This will support new developers and IDEs, as they can still see what they need to create your object.

I agree with the general attitude of the answers here, in any case, this is a viable solution depending on your needs and which is more beneficial for your application.

0
source

Source: https://habr.com/ru/post/1333611/


All Articles