1

Is it a good idea to have all class constructors take in a single array of params, instead of multiple params?

For example,

class A {

    private $id;
    private $name;

    public function __construct($arr) {
    
        foreach ($arr as $key => $val) {
            $this->$key = $val;
        }
    }
}

instead of

class B {

    private $id;
    private $name;

    public function __construct($id, $name) {
       $this->id = $id;
       $this->name = $name;
    }
}

This would eliminate the need to remember the order of arguments, and the need to type $this->key = $val every time I add a new parameter. Are there any downsides to this method?

pbarney
  • 2,529
  • 4
  • 35
  • 49
George Newton
  • 3,153
  • 7
  • 34
  • 49

4 Answers4

3

Though this is really opinion, I would not consider it good practice in general to do this. You would lose your ability to enforce the proper call signature at the function/method boundary. You would lose ability to enforce types for parameters passed (or to provide type hinting for IDEs that support this). So something like this cannot be enforced:

function foo ($bar, PDO $pdo_obj) {}

You also lose your ability to provide default parameter values like this:

function foo ($bar, $optional = 'default') {}

You could also potentially expose the method to unexpected behavior. For example, if one were take the approach you suggest in your example. What is to prevent a caller from passing an array of arbitrary length that could exhaust your memory allocation?

Realistically, you shouldn't even be designing functions that take more than 3 or 4 parameters anyway, so I don't know what you are really gaining here other than to be able to get "parameters" in undefined order. The cost of this "flexibility" is that you then need to create array wrappers around any parameters you would otherwise pass to a function/method directly.

Finally, I would comment that the approach you suggest is just not typical coding practice within PHP. So, if you ever expect someone else to work with your code, then this approach might be confusing to them, as it is just not something that would typically be encountered.

Mike Brant
  • 70,514
  • 10
  • 99
  • 103
2

The downside is that you are more likely to forget to set particular parameters. There are ways to control for that, though. The best way I know of is to create an exception class, such as MissingParameterException, and throw exceptions of that class for any missing required parameters. You can also do type checking and throw exceptions for things that are of the wrong type.

I would add a check like this:

if(property_exists($this, $key)) {
    $this->$key = $val;
}

in order to prevent random unknown properties from getting set by accident.

The thing I worry about is that your objects require so many arguments in the constructor that you can't keep them straight. Please see how-many-constructor-arguments-is-too-many for a discussion about different design patterns.

Community
  • 1
  • 1
miyasudokoro
  • 1,705
  • 1
  • 15
  • 23
2

Downside is that you have no type hinting at all. If you have separate parameters, and you are using a proper IDE like Netbeans or PHPStorm, you will have tools available that help you remember the order of parameters. If you just pass in an array, you don't have that information, no typehinting and no concrete errors in case you forget to add a parameter or add one later and forget to alter a certain call to the constructor.

So I would choose not to do this, although opinions might differ on this subject. In Javascript it seems to be more common. JQuery and other libraries rely heavily on this mechanism, but for PHP, I wouldn't, because of the reasons described above.

GolezTrol
  • 114,394
  • 18
  • 182
  • 210
0

This is bad in my opinion.

Objectively speaking, I think this would make code more difficult to follow for anyone maintaining your codebase given that it is unconventional. Furthermore, I think while you are eliminating the need to remember the order of arguments, you're more likely to introduce bugs because you're adding a layer of obfuscation to the code.

Admittedly, part of the reason I think this is bad is because I first learned programming in java and have biases toward java design patterns and think consistency is important.

Brad
  • 6,106
  • 4
  • 31
  • 43