Use single construct for multiple arguments

109 views Asked by At

In an effort to avoid magic numbers and a bit of future-proofing, i'd like to be able to declare a single constant or variable with multiple constituent elements, to enable a single point to change the values in future.

For example

$myPdf->setFillColor(88, 38, 123) # using this method many times in a routine.

Now the stakeholders want to change the background colour of the pdf (long after requirements sign-off...) so there are many places to change this rgb value. The method setFillColor($r, $g, $b) is from a third party component so I can't change the method to accept a single array argument.

Is there a way to declare a single construct which will unpack into the three, individual, required arguments for the setFillColor() method so something like the following is possible?

$my_color = [88, 38, 123];
$myPdf->setFillColor($my_color);
2

There are 2 answers

0
deceze On BEST ANSWER
define('FOO', [1, 2, 3]);

function f($a, $b, $c) {
    var_dump($a, $b, $c);
}

f(...FOO);

See https://3v4l.org/EGfFN.

If you cannot use the ... operator because you're using an ancient version of PHP, you can also use call_user_func_array:

call_user_func_array([$myPdf, 'setFillColor'], MY_COLOR)

For PHP versions < 7 you can't set the constant to an array, you'll have to use a variable instead.

2
Gabriel Heming On

There's 2 approach to your question.

First of all, let me show you a quote from Clean Code book of Robert C Martin (Chapter 3: Functions. Functions Arguments - Arguments Objects, page 43):

When a function seems to need more than two or three arguments, it is likely that some of those arguments ought to be wrapped into a class of their own.

As I can see, your value represents a RGB color. Why don't just wrap it as a class?

class RGB
{
    private $blue;
    private $green;
    private $red;

    public function __construct($red , $green , $blue)
    {
        $this->red = $red;
        $this->green = $gree;
        $this->blue = $blue;
    }

    /** others necesary methods **/
}

And just use as you want:

$my_color = new RGB(88, 38, 123);
$myPdf->setFillColor($my_color);

And if you need use others kind of colors system, just use an interface:

interface Color { }

RGB implements Color

class RGB implements Color

And a new color system:

class CMYK implements Color
{
    private $cyan;
    private $magenta;
    private $yellow;
    private $black;

    public function __construct($cyan , $magenta , $yellow , black)
    {
        $this->cyan = $cyan;
        $this->magenta = $magenta;
        $this->yellow = $yellow;
        $this->black = $black;
    }
}

The PDF method just need accept an class which implements Color:

public function setFillColor(Color $color)

The second approach, it's not well for Object Oriented, but is using the function argument syntax for PHP >= 5.6 or call_user_func_array to pass a variable number of parameters. Which I can't recommend in your example (for other purpose can be a good ideia), but it exists.